Units can now (optionally) have a RangedAttack animation specified

This commit is contained in:
Andrettin 2015-11-25 13:13:17 +01:00
parent 79d93b7500
commit bf841969a7
8 changed files with 53 additions and 6 deletions

View file

@ -74,6 +74,7 @@ animation.</dd>
<li>Still</li>
<li>Move</li>
<li>Attack</li>
<li>RangedAttack</li>
<li>Repair</li>
<li>Train</li>
<li>Research</li>

View file

@ -83,11 +83,15 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
// No animation.
// So direct fire missile.
// FIXME : wait a little.
if (!unit.Type->Animations || !unit.Type->Animations->Attack) {
order.OnAnimationAttack(unit);
return;
if (unit.Type->Animations && unit.Type->Animations->RangedAttack && unit.IsAttackRanged(order.GetGoal(), order.GetGoalPos())) {
UnitShowAnimation(unit, unit.Type->Animations->RangedAttack);
} else {
if (!unit.Type->Animations || !unit.Type->Animations->Attack) {
order.OnAnimationAttack(unit);
return;
}
UnitShowAnimation(unit, unit.Type->Animations->Attack);
}
UnitShowAnimation(unit, unit.Type->Animations->Attack);
}
/* static */ COrder *COrder::NewActionAttack(const CUnit &attacker, CUnit &target)

View file

@ -703,6 +703,8 @@ static int CclDefineAnimations(lua_State *l)
}
} else if (!strcmp(value, "Attack")) {
anims->Attack = ParseAnimation(l, -1);
} else if (!strcmp(value, "RangedAttack")) {
anims->RangedAttack = ParseAnimation(l, -1);
} else if (!strcmp(value, "SpellCast")) {
anims->SpellCast = ParseAnimation(l, -1);
} else if (!strcmp(value, "Move")) {
@ -732,6 +734,7 @@ static int CclDefineAnimations(lua_State *l)
AddAnimationToArray(anims->Death[i]);
}
AddAnimationToArray(anims->Attack);
AddAnimationToArray(anims->RangedAttack);
AddAnimationToArray(anims->SpellCast);
AddAnimationToArray(anims->Move);
AddAnimationToArray(anims->Repair);

View file

@ -107,7 +107,7 @@ public:
class CAnimations
{
public:
CAnimations() : Attack(NULL), Build(NULL), Move(NULL), Repair(NULL),
CAnimations() : Attack(NULL), RangedAttack(NULL), Build(NULL), Move(NULL), Repair(NULL),
Research(NULL), SpellCast(NULL), Start(NULL), Still(NULL),
Train(NULL), Upgrade(NULL)
{
@ -118,6 +118,7 @@ public:
~CAnimations()
{
delete Attack;
delete RangedAttack;
delete Build;
for (int i = 0; i < ANIMATIONS_DEATHTYPES + 1; ++i) {
delete Death[i];
@ -141,6 +142,7 @@ public:
public:
CAnimation *Attack;
CAnimation *RangedAttack;
CAnimation *Build;
CAnimation *Death[ANIMATIONS_DEATHTYPES + 1];
CAnimation *Harvest[MaxCosts];

View file

@ -286,6 +286,8 @@ public:
int GetDrawLevel() const;
bool IsAttackRanged(CUnit *goal, const Vec2i &goalPos);
PixelPos GetMapPixelPosTopLeft() const;
PixelPos GetMapPixelPosCenter() const;

View file

@ -367,7 +367,10 @@ void FireMissile(CUnit &unit, CUnit *goal, const Vec2i &goalPos)
}
// No missile hits immediately!
if (unit.Type->Missile.Missile->Class == MissileClassNone) {
if (
unit.Type->Missile.Missile->Class == MissileClassNone
|| (unit.Type->Animations && unit.Type->Animations->Attack && unit.Type->Animations->RangedAttack && !unit.IsAttackRanged(goal, goalPos)) // treat melee attacks from units that have both attack and ranged attack animations as having missile class none
) {
// No goal, take target coordinates
if (!goal) {
if (Map.WallOnMap(goalPos)) {

View file

@ -120,6 +120,7 @@ static void MapAnimSounds(CUnitType &type)
MapAnimSounds2(type.Animations->Still);
MapAnimSounds2(type.Animations->Move);
MapAnimSounds2(type.Animations->Attack);
MapAnimSounds2(type.Animations->RangedAttack);
MapAnimSounds2(type.Animations->SpellCast);
for (int i = 0; i <= ANIMATIONS_DEATHTYPES; ++i) {
MapAnimSounds2(type.Animations->Death[i]);

View file

@ -3121,6 +3121,37 @@ bool CUnit::IsUnusable(bool ignore_built_state) const
return (!IsAliveOnMap() || (!ignore_built_state && CurrentAction() == UnitActionBuilt));
}
/**
** Check if the unit attacking its goal will result in a ranged attack
*/
bool CUnit::IsAttackRanged(CUnit *goal, const Vec2i &goalPos)
{
if (this->Variable[ATTACKRANGE_INDEX].Value <= 1) { //always return false if the units attack range is 1 or lower
return false;
}
if (this->Container) { //if the unit is inside a container, the attack will always be ranged
return true;
}
if (
goal
&& goal->IsAliveOnMap()
&& (
this->MapDistanceTo(*goal) > 1
|| (this->Type->UnitType != UnitTypeFly && goal->Type->UnitType == UnitTypeFly)
|| (this->Type->UnitType == UnitTypeFly && goal->Type->UnitType != UnitTypeFly)
)
) {
return true;
}
if (!goal && Map.Info.IsPointOnMap(goalPos) && this->MapDistanceTo(goalPos) > 1) {
return true;
}
return false;
}
/*----------------------------------------------------------------------------
-- Initialize/Cleanup