/*
* Copyright 2010-2016 OpenXcom Developers.
*
* This file is part of OpenXcom.
*
* OpenXcom is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenXcom is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenXcom. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UnitSprite.h"
#include "../Engine/SurfaceSet.h"
#include "../Mod/RuleItem.h"
#include "../Mod/Armor.h"
#include "../Savegame/BattleUnit.h"
#include "../Savegame/BattleItem.h"
#include "../Savegame/Soldier.h"
#include "../Mod/RuleInventory.h"
#include "../Engine/ShaderDraw.h"
#include "../Engine/ShaderMove.h"
#include "../Engine/Options.h"
namespace OpenXcom
{
/**
* Sets up a UnitSprite with the specified size and position.
* @param width Width in pixels.
* @param height Height in pixels.
* @param x X position in pixels.
* @param y Y position in pixels.
*/
UnitSprite::UnitSprite(int width, int height, int x, int y, bool helmet) : Surface(width, height, x, y), _unit(0), _itemR(0), _itemL(0), _unitSurface(0), _itemSurfaceR(0), _itemSurfaceL(0), _part(0), _animationFrame(0), _drawingRoutine(0), _helmet(helmet), _color(0), _colorSize(0)
{
}
/**
* Deletes the UnitSprite.
*/
UnitSprite::~UnitSprite()
{
}
/**
* Changes the surface sets for the UnitSprite to get resources for rendering.
* @param unitSurface Pointer to the unit surface set.
* @param itemSurfaceR Pointer to the item surface set.
* @param itemSurfaceL Pointer to the item surface set.
*/
void UnitSprite::setSurfaces(SurfaceSet *unitSurface, SurfaceSet *itemSurfaceR, SurfaceSet *itemSurfaceL)
{
_unitSurface = unitSurface;
_itemSurfaceR = itemSurfaceR;
_itemSurfaceL = itemSurfaceL;
_redraw = true;
}
/**
* Links this sprite to a BattleUnit to get the data for rendering.
* @param unit Pointer to the BattleUnit.
* @param part The part number for large units.
*/
void UnitSprite::setBattleUnit(BattleUnit *unit, int part)
{
_unit = unit;
_drawingRoutine = _unit->getArmor()->getDrawingRoutine();
_redraw = true;
_part = part;
if (Options::battleHairBleach)
{
_colorSize =_unit->getRecolor().size();
if (_colorSize)
{
_color = &(_unit->getRecolor()[0]);
}
else
{
_color = 0;
}
}
_itemR = unit->getItem("STR_RIGHT_HAND");
if (_itemR && _itemR->getRules()->isFixed())
{
_itemR = 0;
}
_itemL = unit->getItem("STR_LEFT_HAND");
if (_itemL && _itemL->getRules()->isFixed())
{
_itemL = 0;
}
}
namespace
{
struct ColorReplace
{
static const Uint8 ColorGroup = 15<<4;
static const Uint8 ColorShade = 15;
static inline bool loop(Uint8& dest, const Uint8& src, const std::pair<Uint8, Uint8>& face_color)
{
if ((src & ColorGroup) == face_color.first)
{
dest = face_color.second + (src & ColorShade);
return true;
}
else
{
return false;
}
}
static inline void func(Uint8& dest, const Uint8& src, const std::pair<Uint8, Uint8> *color, int size, int)
{
if (src)
{
for (int i = 0; i < size; ++i)
{
if (loop(dest, src, color[i]))
{
return;
}
}
dest = src;
}
}
};
}
void UnitSprite::drawRecolored(Surface *src)
{
if (_colorSize)
{
lock();
ShaderDraw<ColorReplace>(ShaderSurface(this), ShaderSurface(src), ShaderScalar(_color), ShaderScalar(_colorSize));
unlock();
}
else
{
src->blit(this);
}
}
/**
* Sets the animation frame for animated units.
* @param frame Frame number.
*/
void UnitSprite::setAnimationFrame(int frame)
{
_animationFrame = frame;
}
/**
* Draws a unit, using the drawing rules of the unit.
* This function is called by Map, for each unit on the screen.
*/
void UnitSprite::draw()
{
Surface::draw();
// Array of drawing routines
void (UnitSprite::*routines[])() = {&UnitSprite::drawRoutine0,
&UnitSprite::drawRoutine1,
&UnitSprite::drawRoutine2,
&UnitSprite::drawRoutine3,
&UnitSprite::drawRoutine4,
&UnitSprite::drawRoutine5,
&UnitSprite::drawRoutine6,
&UnitSprite::drawRoutine7,
&UnitSprite::drawRoutine8,
&UnitSprite::drawRoutine9,
&UnitSprite::drawRoutine0,
&UnitSprite::drawRoutine11,
&UnitSprite::drawRoutine12,
&UnitSprite::drawRoutine0,
&UnitSprite::drawRoutine0,
&UnitSprite::drawRoutine0,
&UnitSprite::drawRoutine12,
&UnitSprite::drawRoutine4,
&UnitSprite::drawRoutine4,
&UnitSprite::drawRoutine19,
&UnitSprite::drawRoutine20,
&UnitSprite::drawRoutine21,
&UnitSprite::drawRoutine3};
// Call the matching routine
(this->*(routines[_drawingRoutine]))();
}
/**
* Drawing routine for XCom soldiers in overalls, sectoids (routine 0),
* mutons (routine 10),
* aquanauts (routine 13),
* calcinites, deep ones, gill men, lobster men, tasoths (routine 14),
* aquatoids (routine 15) (this one is no different, it just precludes breathing animations.
*/
void UnitSprite::drawRoutine0()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *torso = 0, *legs = 0, *leftArm = 0, *rightArm = 0, *itemR = 0, *itemL = 0;
// magic numbers
const int legsStand = 16, legsKneel = 24;
int maleTorso, femaleTorso, die, rarm1H, larm2H, rarm2H, rarmShoot, legsFloat, torsoHandsWeaponY = 0;
if (_drawingRoutine <= 10)
{
die = 264; // ufo:eu death frame
maleTorso = 32;
femaleTorso = 267;
rarm1H = 232;
larm2H = 240;
rarm2H = 248;
rarmShoot = 256;
legsFloat = 275;
}
else if (_drawingRoutine == 13)
{
if (_helmet)
{
die = 259; // aquanaut underwater death frame
maleTorso = 32; // aquanaut underwater ion armour torso
if (_unit->getArmor()->getForcedTorso() == TORSO_USE_GENDER)
{
femaleTorso = 32; // aquanaut underwater plastic aqua armour torso
}
else
{
femaleTorso = 286; // aquanaut underwater magnetic ion armour torso
}
rarm1H = 248;
larm2H = 232;
rarm2H = rarmShoot = 240;
legsFloat = 294;
}
else
{
die = 256; // aquanaut land death frame
// aquanaut land torso
maleTorso = 270;
femaleTorso = 262;
rarm1H = 248;
larm2H = 232;
rarm2H = rarmShoot = 240;
legsFloat = 294;
}
}
else
{
die = 256; // tftd unit death frame
// tftd unit torso
maleTorso = 32;
femaleTorso = 262;
rarm1H = 248;
larm2H = 232;
rarm2H = rarmShoot = 240;
legsFloat = 294;
}
const int larmStand = 0, rarmStand = 8;
const int legsWalk[8] = { 56, 56+24, 56+24*2, 56+24*3, 56+24*4, 56+24*5, 56+24*6, 56+24*7 };
const int larmWalk[8] = { 40, 40+24, 40+24*2, 40+24*3, 40+24*4, 40+24*5, 40+24*6, 40+24*7 };
const int rarmWalk[8] = { 48, 48+24, 48+24*2, 48+24*3, 48+24*4, 48+24*5, 48+24*6, 48+24*7 };
const int YoffWalk[8] = {1, 0, -1, 0, 1, 0, -1, 0}; // bobbing up and down
const int mutonYoffWalk[8] = {1, 1, 0, 0, 1, 1, 0, 0}; // bobbing up and down (muton)
const int aquatoidYoffWalk[8] = {1, 0, 0, 1, 2, 1, 0, 0}; // bobbing up and down (aquatoid)
const int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons
const int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons
const int offX2[8] = { -8, 3, 5, 12, 6, -1, -5, -13 }; // for the left handed weapons
const int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the left handed weapons
const int offX3[8] = { 0, 0, 2, 2, 0, 0, 0, 0 }; // for the weapons (muton)
const int offY3[8] = { -3, -3, -1, -1, -1, -3, -3, -2 }; // for the weapons (muton)
const int offX4[8] = { -8, 2, 7, 14, 7, -2, -4, -8 }; // for the left handed weapons
const int offY4[8] = { -3, -3, -1, 0, 3, 3, 0, 1 }; // for the left handed weapons
const int offX5[8] = { -1, 1, 1, 2, 0, -1, 0, 0 }; // for the weapons (muton)
const int offY5[8] = { 1, -1, -1, -1, -1, -1, -3, 0 }; // for the weapons (muton)
const int offX6[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles
const int offY6[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles
const int offX7[8] = { 0, 6, 8, 12, 2, -5, -5, -13 }; // for the left handed rifles (muton)
const int offY7[8] = { -4, -6, -1, 0, 3, 0, 1, 0 }; // for the left handed rifles (muton)
const int offYKneel = 4;
const int offXSprite = 16; // sprites are double width
const int soldierHeight = 22;
const int unitDir = _unit->getDirection();
const int walkPhase = _unit->getWalkingPhase();
if (_unit->getStatus() == STATUS_COLLAPSING)
{
torso = _unitSurface->getFrame(die + _unit->getFallingPhase());
torso->setX(offXSprite);
drawRecolored(torso);
return;
}
if (_drawingRoutine == 0 || _helmet)
{
if ((_unit->getGender() == GENDER_FEMALE && _unit->getArmor()->getForcedTorso() != TORSO_ALWAYS_MALE)
|| _unit->getArmor()->getForcedTorso() == TORSO_ALWAYS_FEMALE)
{
torso = _unitSurface->getFrame(femaleTorso + unitDir);
}
else
{
torso = _unitSurface->getFrame(maleTorso + unitDir);
}
}
else
{
if (_unit->getGender() == GENDER_FEMALE)
{
torso = _unitSurface->getFrame(femaleTorso + unitDir);
}
else
{
torso = _unitSurface->getFrame(maleTorso + unitDir);
}
}
// when walking, torso(fixed sprite) has to be animated up/down
if (_unit->getStatus() == STATUS_WALKING)
{
if (_drawingRoutine == 10)
torsoHandsWeaponY = mutonYoffWalk[walkPhase];
else if (_drawingRoutine == 13 || _drawingRoutine == 14)
torsoHandsWeaponY = YoffWalk[walkPhase]+1;
else if (_drawingRoutine == 15)
torsoHandsWeaponY = aquatoidYoffWalk[walkPhase];
else
torsoHandsWeaponY = YoffWalk[walkPhase];
torso->setY(torsoHandsWeaponY);
legs = _unitSurface->getFrame(legsWalk[unitDir] + walkPhase);
leftArm = _unitSurface->getFrame(larmWalk[unitDir] + walkPhase);
rightArm = _unitSurface->getFrame(rarmWalk[unitDir] + walkPhase);
if (_drawingRoutine == 10 && unitDir == 3)
{
leftArm->setY(-1);
}
}
else
{
if (_unit->isKneeled())
{
legs = _unitSurface->getFrame(legsKneel + unitDir);
}
else if (_unit->isFloating() && _unit->getMovementType() == MT_FLY)
{
legs = _unitSurface->getFrame(legsFloat + unitDir);
}
else
{
legs = _unitSurface->getFrame(legsStand + unitDir);
}
leftArm = _unitSurface->getFrame(larmStand + unitDir);
rightArm = _unitSurface->getFrame(rarmStand + unitDir);
}
sortRifles();
// holding an item
if (_itemR)
{
// draw handob item
if (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + dir);
itemR->setX(offX[unitDir]);
itemR->setY(offY[unitDir]);
}
else
{
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + unitDir);
if (_drawingRoutine == 10)
{
if (_itemR->getRules()->isTwoHanded())
{
itemR->setX(offX3[unitDir]);
itemR->setY(offY3[unitDir]);
}
else
{
itemR->setX(offX5[unitDir]);
itemR->setY(offY5[unitDir]);
}
}
else
{
itemR->setX(0);
itemR->setY(0);
}
}
// draw arms holding the item
if (_itemR->getRules()->isTwoHanded())
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
if (_unit->getStatus() == STATUS_AIMING)
{
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
else
{
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
}
else
{
if (_drawingRoutine == 10)
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
else
rightArm = _unitSurface->getFrame(rarm1H + unitDir);
}
// the fixed arm(s) have to be animated up/down when walking
if (_unit->getStatus() == STATUS_WALKING)
{
itemR->setY(itemR->getY() + torsoHandsWeaponY);
rightArm->setY(torsoHandsWeaponY);
if (_itemR->getRules()->isTwoHanded())
leftArm->setY(torsoHandsWeaponY);
}
}
//if we are left handed or dual wielding...
if (_itemL)
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + unitDir);
if (!_itemL->getRules()->isTwoHanded())
{
if (_drawingRoutine == 10)
{
itemL->setX(offX4[unitDir]);
itemL->setY(offY4[unitDir]);
}
else
{
itemL->setX(offX2[unitDir]);
itemL->setY(offY2[unitDir]);
}
}
else
{
itemL->setX(0);
itemL->setY(0);
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
if (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + dir);
if (_drawingRoutine == 10)
{
itemL->setX(offX7[unitDir]);
itemL->setY(offY7[unitDir]);
}
else
{
itemL->setX(offX6[unitDir]);
itemL->setY(offY6[unitDir]);
}
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
if (_unit->getStatus() == STATUS_WALKING)
{
itemL->setY(itemL->getY() + torsoHandsWeaponY);
leftArm->setY(torsoHandsWeaponY);
if (_itemL->getRules()->isTwoHanded())
rightArm->setY(torsoHandsWeaponY);
}
}
// offset everything but legs when kneeled
if (_unit->isKneeled())
{
if (_drawingRoutine == 13) // tftd torsos are stubby.
{
leftArm->setY(offYKneel + 1);
rightArm->setY(offYKneel + 1);
torso->setY(offYKneel + 1);
itemR?itemR->setY(itemR->getY() + offYKneel + 1):void();
itemL?itemL->setY(itemL->getY() + offYKneel + 1):void();
}
else
{
leftArm->setY(offYKneel);
rightArm->setY(offYKneel);
torso->setY(offYKneel);
itemR?itemR->setY(itemR->getY() + offYKneel):void();
itemL?itemL->setY(itemL->getY() + offYKneel):void();
}
}
else if (_unit->getStatus() != STATUS_WALKING)
{
leftArm->setY(0);
rightArm->setY(0);
torso->setY(0);
}
// items are calculated for soldier height (22) - some aliens are smaller, so item is drawn lower.
if (itemR)
{
itemR->setY(itemR->getY() + (soldierHeight - _unit->getStandHeight()));
}
if (itemL)
{
itemL->setY(itemL->getY() + (soldierHeight - _unit->getStandHeight()));
}
// offset everything to the left by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
torso->setX(offXSprite);
legs->setX(offXSprite);
leftArm->setX(offXSprite);
rightArm->setX(offXSprite);
if (itemR)
itemR->setX(itemR->getX() + offXSprite);
if (itemL)
itemL->setX(itemL->getX() + offXSprite);
// fix the errant muton arm.
if (!itemR && _drawingRoutine == 10 && _unit->getStatus() == STATUS_WALKING && unitDir == 2)
{
rightArm->setX(10);
}
// blit order depends on unit direction, and whether we are holding a 2 handed weapon.
switch (unitDir)
{
case 0: itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); break;
case 1: drawRecolored(leftArm); drawRecolored(legs); itemL?itemL->blit(this):void(); drawRecolored(torso); itemR?itemR->blit(this):void(); drawRecolored(rightArm); break;
case 2: drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); itemL?itemL->blit(this):void(); itemR?itemR->blit(this):void(); drawRecolored(rightArm); break;
case 3:
if (_unit->getStatus() != STATUS_AIMING && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))
{
drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(rightArm);
}
else
{
drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void();
}
break;
case 4: drawRecolored(legs); drawRecolored(rightArm); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 5:
if (_unit->getStatus() != STATUS_AIMING && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))
{
drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void();
}
else
{
drawRecolored(rightArm); drawRecolored(legs); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(torso); drawRecolored(leftArm);
}
break;
case 6: drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); break;
case 7:
if (_unit->getStatus() != STATUS_AIMING && ((_itemR && _itemR->getRules()->isTwoHanded()) || (_itemL && _itemL->getRules()->isTwoHanded())))
{
drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso);
}
else
{
itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso);
}
break;
}
torso->setX(0);
legs->setX(0);
leftArm->setX(0);
rightArm->setX(0);
if (itemR)
itemR->setX(0);
if (itemL)
itemL->setX(0);
}
/**
* Drawing routine for floaters.
*/
void UnitSprite::drawRoutine1()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *torso = 0, *leftArm = 0, *rightArm = 0, *itemR = 0, *itemL = 0;
// magic numbers
const int stand = 16, walk = 24, die = 64;
const int larm = 8, rarm = 0, larm2H = 67, rarm2H = 75, rarmShoot = 83, rarm1H= 91; // note that arms are switched vs "normal" sheets
const int yoffWalk[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // bobbing up and down
const int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons
const int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons
const int offX2[8] = { -8, 3, 7, 13, 6, -3, -5, -13 }; // for the weapons
const int offY2[8] = { 1, -4, -1, 0, 3, 3, 5, 0 }; // for the weapons
const int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles
const int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_COLLAPSING)
{
torso = _unitSurface->getFrame(die + _unit->getFallingPhase());
torso->setX(offXSprite);
drawRecolored(torso);
return;
}
const int unitDir = _unit->getDirection();
const int walkPhase = _unit->getWalkingPhase();
leftArm = _unitSurface->getFrame(larm + unitDir);
rightArm = _unitSurface->getFrame(rarm + unitDir);
// when walking, torso(fixed sprite) has to be animated up/down
if (_unit->getStatus() == STATUS_WALKING)
{
torso = _unitSurface->getFrame(walk + (5 * unitDir) + (walkPhase / 1.6)); // floater only has 5 walk animations instead of 8
torso->setY(yoffWalk[walkPhase]);
}
else
{
torso = _unitSurface->getFrame(stand + unitDir);
}
sortRifles();
// holding an item
if (_itemR)
{
// draw handob item
if (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())
{
int dir = (_unit->getDirection() + 2)%8;
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + dir);
itemR->setX(offX[unitDir]);
itemR->setY(offY[unitDir]);
}
else
{
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + unitDir);
itemR->setX(0);
itemR->setY(0);
}
// draw arms holding the item
if (_itemR->getRules()->isTwoHanded())
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
if (_unit->getStatus() == STATUS_AIMING)
{
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
else
{
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
}
else
{
rightArm = _unitSurface->getFrame(rarm1H + unitDir);
}
}
//if we are left handed or dual wielding...
if (_itemL)
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + unitDir);
if (!_itemL->getRules()->isTwoHanded())
{
itemL->setX(offX2[unitDir]);
itemL->setY(offY2[unitDir]);
}
else
{
itemL->setX(0);
itemL->setY(0);
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
if (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + dir);
itemL->setX(offX3[unitDir]);
itemL->setY(offY3[unitDir]);
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
if (_unit->getStatus() == STATUS_WALKING)
{
leftArm->setY(yoffWalk[walkPhase]);
itemL->setY(itemL->getY() + yoffWalk[walkPhase]);
if (_itemL->getRules()->isTwoHanded())
rightArm->setY(yoffWalk[walkPhase]);
}
}
if (_unit->getStatus() != STATUS_WALKING)
{
leftArm->setY(0);
rightArm->setY(0);
torso->setY(0);
}
// offset everything to the left by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
torso->setX(offXSprite);
leftArm->setX(offXSprite);
rightArm->setX(offXSprite);
if (itemR)
itemR->setX(itemR->getX() + offXSprite);
if (itemL)
itemL->setX(itemL->getX() + offXSprite);
// blit order depends on unit direction.
switch (unitDir)
{
case 0: itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(torso); drawRecolored(rightArm); break;
case 1: drawRecolored(leftArm); drawRecolored(torso); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 2: drawRecolored(leftArm); drawRecolored(torso); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 3: drawRecolored(torso); drawRecolored(leftArm); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 4: drawRecolored(torso); drawRecolored(leftArm); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 5: drawRecolored(rightArm); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 6: drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(torso); drawRecolored(leftArm); break;
case 7: drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(torso); break;
}
torso->setX(0);
leftArm->setX(0);
rightArm->setX(0);
if (itemR)
itemR->setX(0);
if (itemL)
itemL->setX(0);
}
/**
* Drawing routine for XCom tanks.
*/
void UnitSprite::drawRoutine2()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
const int offX[8] = { -2, -7, -5, 0, 5, 7, 2, 0 }; // hovertank offsets
const int offy[8] = { -1, -3, -4, -5, -4, -3, -1, -1 }; // hovertank offsets
const int offXSprite = 16; // sprites are double width
Surface *s = 0;
const int hoverTank = _unit->getMovementType() == MT_FLY ? 32 : 0;
const int turret = _unit->getTurretType();
// draw the animated propulsion below the hwp
if (_part > 0 && hoverTank != 0)
{
s = _unitSurface->getFrame(104 + ((_part-1) * 8) + _animationFrame);
s->setX(offXSprite);
drawRecolored(s);
}
// draw the tank itself
s = _unitSurface->getFrame(hoverTank + (_part * 8) + _unit->getDirection());
s->setX(offXSprite);
drawRecolored(s);
// draw the turret, together with the last part
if (_part == 3 && turret != -1)
{
s = _unitSurface->getFrame(64 + (turret * 8) + _unit->getTurretDirection());
int turretOffsetX = 0;
int turretOffsetY = -4;
if (hoverTank)
{
turretOffsetX += offX[_unit->getDirection()];
turretOffsetY += offy[_unit->getDirection()];
}
s->setX(turretOffsetX + offXSprite);
s->setY(turretOffsetY);
drawRecolored(s);
}
}
/**
* Drawing routine for cyberdiscs. (3)
* and helicopters (22)
*/
void UnitSprite::drawRoutine3()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0;
const int offXSprite = 16; // sprites are double width
// draw the animated propulsion below the hwp
if (_drawingRoutine == 3)
{
if (_part > 0)
{
s = _unitSurface->getFrame(32 + ((_part-1) * 8) + _animationFrame);
s->setX(offXSprite);
drawRecolored(s);
}
}
s = _unitSurface->getFrame((_part * 8) + _unit->getDirection());
// offset everything to the left by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
s->setX(offXSprite);
drawRecolored(s);
// draw the animated propulsion above the hwp
if (_drawingRoutine == 22)
{
if (_part > 0)
{
s = _unitSurface->getFrame(32 + ((_part-1) * 8) + _animationFrame);
s->setX(offXSprite);
drawRecolored(s);
}
}
}
/**
* Drawing routine for civilians, ethereals, zombies (routine 4),
* tftd civilians, tftd zombies (routine 17), more tftd civilians (routine 18).
* Very easy: first 8 is standing positions, then 8 walking sequences of 8, finally death sequence of 3
*/
void UnitSprite::drawRoutine4()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0, *itemR = 0, *itemL = 0;
int stand = 0, walk = 8, die = 72;
const int offX[8] = { 8, 10, 7, 4, -9, -11, -7, -3 }; // for the weapons
const int offY[8] = { -6, -3, 0, 2, 0, -4, -7, -9 }; // for the weapons
const int offX2[8] = { -8, 3, 5, 12, 6, -1, -5, -13 }; // for the weapons
const int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the weapons
const int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles
const int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles
const int standConvert[8] = { 3, 2, 1, 0, 7, 6, 5, 4 }; // array for converting stand frames for some tftd civilians
const int offXSprite = 16; // sprites are double width
if (_drawingRoutine == 17) // tftd civilian - first set
{
stand = 64;
walk = 0;
}
else if (_drawingRoutine == 18) // tftd civilian - second set
{
stand = 140;
walk = 76;
die = 148;
}
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
const int unitDir = _unit->getDirection();
if (_unit->getStatus() == STATUS_COLLAPSING)
{
s = _unitSurface->getFrame(die + _unit->getFallingPhase());
s->setX(offXSprite);
drawRecolored(s);
return;
}
else if (_unit->getStatus() == STATUS_WALKING)
{
s = _unitSurface->getFrame(walk + (8 * unitDir) + _unit->getWalkingPhase());
}
else if (_drawingRoutine != 17)
{
s = _unitSurface->getFrame(stand + unitDir);
}
else
{
s = _unitSurface->getFrame(stand + standConvert[unitDir]);
}
sortRifles();
if (_itemR && !_itemR->getRules()->isFixed())
{
// draw handob item
if (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + dir);
itemR->setX(offX[unitDir]);
itemR->setY(offY[unitDir]);
}
else
{
if (_itemR->getSlot()->getId() == "STR_RIGHT_HAND")
{
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + unitDir);
itemR->setX(0);
itemR->setY(0);
}
else
{
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + unitDir);
itemR->setX(offX2[unitDir]);
itemR->setY(offY2[unitDir]);
}
}
}
//if we are dual wielding...
if (_itemL && !_itemL->getRules()->isFixed())
{
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + unitDir);
if (!_itemL->getRules()->isTwoHanded())
{
itemL->setX(offX2[unitDir]);
itemL->setY(offY2[unitDir]);
}
else
{
itemL->setX(0);
itemL->setY(0);
}
if (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + dir);
itemL->setX(offX3[unitDir]);
itemL->setY(offY3[unitDir]);
}
}
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
s->setX(offXSprite);
if (itemR)
itemR->setX(itemR->getX() + offXSprite);
if (itemL)
itemL->setX(itemL->getX() + offXSprite);
switch (unitDir)
{
case 0: itemL?itemL->blit(this):void(); itemR?itemR->blit(this):void(); drawRecolored(s); break;
case 1: itemL?itemL->blit(this):void(); drawRecolored(s); itemR?itemR->blit(this):void(); break;
case 2: drawRecolored(s); itemL?itemL->blit(this):void(); itemR?itemR->blit(this):void(); break;
case 3: drawRecolored(s); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 4: drawRecolored(s); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 5: itemR?itemR->blit(this):void(); drawRecolored(s); itemL?itemL->blit(this):void(); break;
case 6: itemR?itemR->blit(this):void(); drawRecolored(s); itemL?itemL->blit(this):void(); break;
case 7: itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(s); break;
}
s->setX(0);
if (itemR)
itemR->setX(0);
if (itemL)
itemL->setX(0);
}
/**
* Drawing routine for sectopods and reapers.
*/
void UnitSprite::drawRoutine5()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0;
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_WALKING)
{
s = _unitSurface->getFrame( 32 + (_unit->getDirection() * 16) + (_part * 4) + ((_unit->getWalkingPhase() / 2) % 4));
}
else
{
s = _unitSurface->getFrame((_part * 8) + _unit->getDirection());
}
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
s->setX(offXSprite);
drawRecolored(s);
}
/**
* Drawing routine for snakemen.
*/
void UnitSprite::drawRoutine6()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *torso = 0, *legs = 0, *leftArm = 0, *rightArm = 0, *itemR = 0, *itemL = 0;
// magic numbers
const int Torso = 24, legsStand = 16, die = 96;
const int larmStand = 0, rarmStand = 8, rarm1H = 99, larm2H = 107, rarm2H = 115, rarmShoot = 123;
const int legsWalk[8] = { 32, 40, 48, 56, 64, 72, 80, 88 };
const int yoffWalk[8] = {3, 3, 2, 1, 0, 0, 1, 2}; // bobbing up and down
const int xoffWalka[8] = {0, 0, 1, 2, 3, 3, 2, 1};
const int xoffWalkb[8] = {0, 0, -1, -2, -3, -3, -2, -1};
const int yoffStand[8] = {2, 1, 1, 0, 0, 0, 0, 0};
const int offX[8] = { 8, 10, 5, 2, -8, -10, -5, -2 }; // for the weapons
const int offY[8] = { -6, -3, 0, 0, 2, -3, -7, -9 }; // for the weapons
const int offX2[8] = { -8, 2, 7, 13, 7, 0, -3, -15 }; // for the weapons
const int offY2[8] = { 1, -4, -2, 0, 3, 3, 5, 0 }; // for the weapons
const int offX3[8] = { 0, 6, 6, 12, -4, -5, -5, -13 }; // for the left handed rifles
const int offY3[8] = { -4, -4, -1, 0, 5, 0, 1, 0 }; // for the left handed rifles
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_COLLAPSING)
{
torso = _unitSurface->getFrame(die + _unit->getFallingPhase());
torso->setX(offXSprite);
drawRecolored(torso);
return;
}
const int unitDir = _unit->getDirection();
const int walkPhase = _unit->getWalkingPhase();
torso = _unitSurface->getFrame(Torso + unitDir);
leftArm = _unitSurface->getFrame(larmStand + unitDir);
rightArm = _unitSurface->getFrame(rarmStand + unitDir);
// when walking, torso(fixed sprite) has to be animated up/down
if (_unit->getStatus() == STATUS_WALKING)
{
int xoffWalk = 0;
if (unitDir < 3)
xoffWalk = xoffWalka[walkPhase];
if (unitDir < 7 && unitDir > 3)
xoffWalk = xoffWalkb[walkPhase];
torso->setY(yoffWalk[walkPhase]);
torso->setX(xoffWalk);
legs = _unitSurface->getFrame(legsWalk[unitDir] + walkPhase);
rightArm->setY(yoffWalk[walkPhase]);
leftArm->setY(yoffWalk[walkPhase]);
rightArm->setX(xoffWalk);
leftArm->setX(xoffWalk);
}
else
{
legs = _unitSurface->getFrame(legsStand + unitDir);
}
sortRifles();
// holding an item
if (_itemR)
{
// draw handob item
if (_unit->getStatus() == STATUS_AIMING && _itemR->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + dir);
itemR->setX(offX[unitDir]);
itemR->setY(offY[unitDir]);
}
else
{
itemR = _itemSurfaceR->getFrame(_itemR->getRules()->getHandSprite() + unitDir);
itemR->setX(0);
itemR->setY(0);
if (!_itemR->getRules()->isTwoHanded())
{
itemR->setY(yoffStand[unitDir]);
}
}
// draw arms holding the item
if (_itemR->getRules()->isTwoHanded())
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
if (_unit->getStatus() == STATUS_AIMING)
{
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
else
{
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
}
else
{
rightArm = _unitSurface->getFrame(rarm1H + unitDir);
}
// the fixed arm(s) have to be animated up/down when walking
if (_unit->getStatus() == STATUS_WALKING)
{
itemR->setY(yoffWalk[walkPhase]);
rightArm->setY(yoffWalk[walkPhase]);
if (_itemR->getRules()->isTwoHanded())
leftArm->setY(yoffWalk[walkPhase]);
}
}
//if we are left handed or dual wielding...
if (_itemL)
{
leftArm = _unitSurface->getFrame(larm2H + unitDir);
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + unitDir);
if (!_itemL->getRules()->isTwoHanded())
{
itemL->setX(offX2[unitDir]);
itemL->setY(offY2[unitDir]);
}
else
{
itemL->setX(0);
itemL->setY(0);
if (!_itemL->getRules()->isTwoHanded())
{
itemL->setY(yoffStand[unitDir]);
}
rightArm = _unitSurface->getFrame(rarm2H + unitDir);
}
if (_unit->getStatus() == STATUS_AIMING && _itemL->getRules()->isTwoHanded())
{
int dir = (unitDir + 2)%8;
itemL = _itemSurfaceL->getFrame(_itemL->getRules()->getHandSprite() + dir);
itemL->setX(offX3[unitDir]);
itemL->setY(offY3[unitDir]);
rightArm = _unitSurface->getFrame(rarmShoot + unitDir);
}
if (_unit->getStatus() == STATUS_WALKING)
{
leftArm->setY(yoffWalk[walkPhase]);
itemL->setY(offY2[unitDir] + yoffWalk[walkPhase]);
if (_itemL->getRules()->isTwoHanded())
rightArm->setY(yoffWalk[walkPhase]);
}
}
// offset everything but legs when kneeled
if (_unit->getStatus() != STATUS_WALKING)
{
leftArm->setY(0);
rightArm->setY(0);
torso->setY(0);
}
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
torso->setX(offXSprite);
legs->setX(offXSprite);
leftArm->setX(offXSprite);
rightArm->setX(offXSprite);
if (itemR)
itemR->setX(itemR->getX() + offXSprite);
if (itemL)
itemL->setX(itemL->getX() + offXSprite);
// blit order depends on unit direction.
switch (unitDir)
{
case 0: itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); break;
case 1: drawRecolored(leftArm); drawRecolored(legs); itemL?itemL->blit(this):void(); drawRecolored(torso); itemR?itemR->blit(this):void(); drawRecolored(rightArm); break;
case 2: drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 3: drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); drawRecolored(rightArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 4: drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 5: drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); break;
case 6: drawRecolored(rightArm); drawRecolored(legs); itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(torso); drawRecolored(leftArm); break;
case 7: itemR?itemR->blit(this):void(); itemL?itemL->blit(this):void(); drawRecolored(leftArm); drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); break;
}
torso->setX(0);
legs->setX(0);
leftArm->setX(0);
rightArm->setX(0);
if (itemR)
itemR->setX(itemR->getX() + 0);
if (itemL)
itemL->setX(itemL->getX() + 0);
}
/**
* Drawing routine for chryssalid.
*/
void UnitSprite::drawRoutine7()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *torso = 0, *legs = 0, *leftArm = 0, *rightArm = 0;
// magic numbers
const int Torso = 24, legsStand = 16, die = 224;
const int larmStand = 0, rarmStand = 8;
const int legsWalk[8] = { 48, 48+24, 48+24*2, 48+24*3, 48+24*4, 48+24*5, 48+24*6, 48+24*7 };
const int larmWalk[8] = { 32, 32+24, 32+24*2, 32+24*3, 32+24*4, 32+24*5, 32+24*6, 32+24*7 };
const int rarmWalk[8] = { 40, 40+24, 40+24*2, 40+24*3, 40+24*4, 40+24*5, 40+24*6, 40+24*7 };
const int yoffWalk[8] = {1, 0, -1, 0, 1, 0, -1, 0}; // bobbing up and down
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_COLLAPSING)
{
torso = _unitSurface->getFrame(die + _unit->getFallingPhase());
torso->setX(offXSprite);
drawRecolored(torso);
return;
}
const int unitDir = _unit->getDirection();
const int walkPhase = _unit->getWalkingPhase();
torso = _unitSurface->getFrame(Torso + unitDir);
// when walking, torso(fixed sprite) has to be animated up/down
if (_unit->getStatus() == STATUS_WALKING)
{
torso->setY(yoffWalk[walkPhase]);
legs = _unitSurface->getFrame(legsWalk[unitDir] + walkPhase);
leftArm = _unitSurface->getFrame(larmWalk[unitDir] + walkPhase);
rightArm = _unitSurface->getFrame(rarmWalk[unitDir] + walkPhase);
}
else
{
legs = _unitSurface->getFrame(legsStand + unitDir);
leftArm = _unitSurface->getFrame(larmStand + unitDir);
rightArm = _unitSurface->getFrame(rarmStand + unitDir);
leftArm->setY(0);
rightArm->setY(0);
torso->setY(0);
}
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
torso->setX(offXSprite);
legs->setX(offXSprite);
leftArm->setX(offXSprite);
rightArm->setX(offXSprite);
// blit order depends on unit direction
switch (unitDir)
{
case 0: drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); break;
case 1: drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); break;
case 2: drawRecolored(leftArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(rightArm); break;
case 3: drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); drawRecolored(rightArm); break;
case 4: drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); break;
case 5: drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); break;
case 6: drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); drawRecolored(leftArm); break;
case 7: drawRecolored(leftArm); drawRecolored(rightArm); drawRecolored(legs); drawRecolored(torso); break;
}
}
/**
* Drawing routine for silacoids.
*/
void UnitSprite::drawRoutine8()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *legs = 0;
// magic numbers
const int Body = 0, aim = 5, die = 6;
const int Pulsate[8] = { 0, 1, 2, 3, 4, 3, 2, 1 };
const int offXSprite = 16; // sprites are double width
legs = _unitSurface->getFrame(Body + Pulsate[_animationFrame]);
_redraw = true;
if (_unit->getStatus() == STATUS_COLLAPSING)
legs = _unitSurface->getFrame(die + _unit->getFallingPhase());
else if (_unit->getStatus() == STATUS_AIMING)
legs = _unitSurface->getFrame(aim);
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
legs->setX(offXSprite);
drawRecolored(legs);
}
/**
* Drawing routine for celatids.
*/
void UnitSprite::drawRoutine9()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *torso = 0;
// magic numbers
const int Body = 0, die = 25;
const int offXSprite = 16; // sprites are double width
torso = _unitSurface->getFrame(Body + _animationFrame);
_redraw = true;
if (_unit->getStatus() == STATUS_COLLAPSING)
torso = _unitSurface->getFrame(die + _unit->getFallingPhase());
// offset everything to the right by 16 pixels.
// this is because we draw the sprites double wide, to accommodate weapons in-hand
torso->setX(offXSprite);
drawRecolored(torso);
}
/**
* Drawing routine for tftd tanks.
*/
void UnitSprite::drawRoutine11()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
const int offTurretX[8] = { -2, -6, -5, 0, 5, 6, 2, 0 }; // turret offsets
const int offTurretYAbove[8] = { 5, 3, 0, 0, 0, 3, 5, 4 }; // turret offsets
const int offTurretYBelow[8] = { -11, -13, -16, -16, -16, -13, -11, -12 }; // turret offsets
const int offXSprite = 16; // sprites are double width
int body = 0;
int animFrame = _unit->getWalkingPhase() % 4;
if (_unit->getMovementType() == MT_FLY)
{
body = 128;
animFrame = _animationFrame % 4;
}
Surface *s = _unitSurface->getFrame(body + (_part * 4) + 16 * _unit->getDirection() + animFrame);
s->setY(4);
s->setX(offXSprite);
drawRecolored(s);
int turret = _unit->getTurretType();
// draw the turret, overlapping all 4 parts
if ((_part == 3 || _part == 0) && turret != -1 && !_unit->getFloorAbove())
{
s = _unitSurface->getFrame(256 + (turret * 8) + _unit->getTurretDirection());
s->setX(offTurretX[_unit->getDirection()] + offXSprite);
if (_part == 3)
s->setY(offTurretYBelow[_unit->getDirection()]);
else
s->setY(offTurretYAbove[_unit->getDirection()]);
drawRecolored(s);
}
}
/**
* Drawing routine for hallucinoids (routine 12) and biodrones (routine 16).
*/
void UnitSprite::drawRoutine12()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
const int die = 8;
const int offXSprite = 16; // sprites are double width
Surface *s = 0;
s = _unitSurface->getFrame((_part * 8) + _animationFrame);
_redraw = true;
if ( (_unit->getStatus() == STATUS_COLLAPSING) && (_drawingRoutine == 16) )
{
// biodrone death frames
s = _unitSurface->getFrame(die + _unit->getFallingPhase());
}
s->setX(offXSprite);
drawRecolored(s);
}
/**
* Drawing routine for tentaculats.
*/
void UnitSprite::drawRoutine19()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0;
// magic numbers
const int stand = 0, move = 8, die = 16;
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_COLLAPSING)
{
s = _unitSurface->getFrame(die + _unit->getFallingPhase());
}
else if (_unit->getStatus() == STATUS_WALKING)
{
s = _unitSurface->getFrame(move + _unit->getDirection());
}
else
{
s = _unitSurface->getFrame(stand + _unit->getDirection());
}
s->setX(offXSprite);
drawRecolored(s);
}
/**
* Drawing routine for triscenes.
*/
void UnitSprite::drawRoutine20()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0;
const int offXSprite = 16; // sprites are double width
if (_unit->getStatus() == STATUS_WALKING)
{
s = _unitSurface->getFrame((_unit->getWalkingPhase()/2%4) + 5 * (_part + 4 * _unit->getDirection()));
}
else
{
s = _unitSurface->getFrame(5 * (_part + 4 * _unit->getDirection()));
}
s->setX(offXSprite);
drawRecolored(s);
}
/**
* Drawing routine for xarquids.
*/
void UnitSprite::drawRoutine21()
{
if (_unit->isOut())
{
// unit is drawn as an item
return;
}
Surface *s = 0;
const int offXSprite = 16; // sprites are double width
s = _unitSurface->getFrame((_part * 4) + (_unit->getDirection() * 16) + (_animationFrame % 4));
_redraw = true;
s->setX(offXSprite);
drawRecolored(s);
}
/**
* Determines which weapons to display in the case of two-handed weapons.
*/
void UnitSprite::sortRifles()
{
if (_itemR && _itemR->getRules()->isTwoHanded())
{
if (_itemL && _itemL->getRules()->isTwoHanded())
{
if (_unit->getActiveHand() == "STR_LEFT_HAND")
{
_itemR = _itemL;
}
_itemL = 0;
}
else if (_unit->getStatus() != STATUS_AIMING)
{
_itemL = 0;
}
}
else if (_itemL && _itemL->getRules()->isTwoHanded())
{
if (_unit->getStatus() != STATUS_AIMING)
{
_itemR = 0;
}
}
}
}
↑ V1037 Two or more case-branches perform the same actions. Check lines: 736, 737
↑ V1037 Two or more case-branches perform the same actions. Check lines: 738, 739
↑ V1037 Two or more case-branches perform the same actions. Check lines: 979, 980
↑ V1037 Two or more case-branches perform the same actions. Check lines: 981, 982
↑ V1037 Two or more case-branches perform the same actions. Check lines: 1202, 1203
↑ V1037 Two or more case-branches perform the same actions. Check lines: 1280, 1281, 1282
↑ V1037 Two or more case-branches perform the same actions. Check lines: 1284, 1285, 1286