[+] Added CUnit flag Summoned to mark units which are summoned by spells
[*] Summoned units don't bother AI when attacked and join into AI attack forces to help in attack wave [*] Some animation code clean-up
This commit is contained in:
parent
a5d5580115
commit
13ffa1d0b3
27 changed files with 219 additions and 123 deletions
src
ai
animation
animation.cppanimation_exactframe.cppanimation_frame.cppanimation_ifvar.cppanimation_luacallback.cppanimation_move.cppanimation_randomgoto.cppanimation_randomrotate.cppanimation_randomwait.cppanimation_rotate.cppanimation_setplayervar.cppanimation_setvar.cppanimation_spawnmissile.cppanimation_spawnunit.cppanimation_wait.cpp
include
spell
unit
|
@ -670,7 +670,7 @@ void AiHelpMe(const CUnit *attacker, CUnit &defender)
|
|||
return;
|
||||
}
|
||||
// Summoned unit, don't help
|
||||
if (defender.GroupId == -1) {
|
||||
if (defender.Summoned) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -467,6 +467,30 @@ unsigned int AiForceManager::FindFreeForce(AiForceRole role, int begin)
|
|||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find unit in force
|
||||
**
|
||||
** @param unit Unit to search for.
|
||||
**
|
||||
** @return Force number, or -1 if not found
|
||||
*/
|
||||
|
||||
int AiForceManager::GetForce(const CUnit &unit)
|
||||
{
|
||||
for (unsigned int i = 0; i < forces.size(); ++i) {
|
||||
AiForce &force = forces[i];
|
||||
|
||||
for (unsigned int j = 0; j < force.Units.size(); ++j) {
|
||||
CUnit &aiunit = *force.Units[j];
|
||||
|
||||
if (UnitNumber(unit) == UnitNumber(aiunit)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Cleanup units in forces.
|
||||
*/
|
||||
|
|
|
@ -159,12 +159,12 @@ public:
|
|||
|
||||
void ReturnToHome();
|
||||
bool NewRallyPoint(const Vec2i &startPos, Vec2i *resultPos);
|
||||
void Insert(CUnit &unit);
|
||||
|
||||
private:
|
||||
void CountTypes(unsigned int *counter, const size_t len);
|
||||
bool IsBelongsTo(const CUnitType &type);
|
||||
void Insert(CUnit &unit);
|
||||
|
||||
|
||||
void Update();
|
||||
|
||||
static void InternalRemoveUnit(CUnit *unit);
|
||||
|
@ -220,6 +220,7 @@ public:
|
|||
return script[index];
|
||||
}
|
||||
|
||||
int GetForce(const CUnit &unit);
|
||||
void RemoveDeadUnit();
|
||||
bool Assign(CUnit &unit);
|
||||
void Update();
|
||||
|
|
|
@ -134,17 +134,17 @@ static int ParseAnimPlayer(const CUnit &unit, const char *parseint)
|
|||
** @return The parsed value.
|
||||
*/
|
||||
|
||||
int ParseAnimInt(const CUnit *unit, const char *parseint)
|
||||
int ParseAnimInt(const CUnit &unit, const char *parseint)
|
||||
{
|
||||
char s[100];
|
||||
const CUnit *goal = unit;
|
||||
const CUnit *goal = &unit;
|
||||
|
||||
strcpy(s, parseint);
|
||||
char *cur = &s[2];
|
||||
if ((s[0] == 'v' || s[0] == 't') && unit != NULL) { //unit variable detected
|
||||
if (s[0] == 'v' || s[0] == 't') { //unit variable detected
|
||||
if (s[0] == 't') {
|
||||
if (unit->CurrentOrder()->HasGoal()) {
|
||||
goal = unit->CurrentOrder()->GetGoal();
|
||||
if (unit.CurrentOrder()->HasGoal()) {
|
||||
goal = unit.CurrentOrder()->GetGoal();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
char *next = strchr(cur, '.');
|
||||
if (next == NULL) {
|
||||
fprintf(stderr, "Need also specify the variable '%s' tag \n", cur);
|
||||
Exit(1);
|
||||
ExitFatal(1);
|
||||
} else {
|
||||
*next = '\0';
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
return goal->Resource.Active;
|
||||
}
|
||||
fprintf(stderr, "Bad variable name '%s'\n", cur);
|
||||
Exit(1);
|
||||
ExitFatal(1);
|
||||
}
|
||||
if (!strcmp(next + 1, "Value")) {
|
||||
return goal->Variable[index].Value;
|
||||
|
@ -178,10 +178,10 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
return goal->Variable[index].Value * 100 / goal->Variable[index].Max;
|
||||
}
|
||||
return 0;
|
||||
} else if ((s[0] == 'b' || s[0] == 'g') && unit != NULL) { //unit bool flag detected
|
||||
} else if (s[0] == 'b' || s[0] == 'g') { //unit bool flag detected
|
||||
if (s[0] == 'g') {
|
||||
if (unit->CurrentOrder()->HasGoal()) {
|
||||
goal = unit->CurrentOrder()->GetGoal();
|
||||
if (unit.CurrentOrder()->HasGoal()) {
|
||||
goal = unit.CurrentOrder()->GetGoal();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -189,11 +189,10 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
const int index = UnitTypeVar.BoolFlagNameLookup[cur];// User bool flags
|
||||
if (index == -1) {
|
||||
fprintf(stderr, "Bad bool-flag name '%s'\n", cur);
|
||||
Exit(1);
|
||||
return 0;
|
||||
ExitFatal(1);
|
||||
}
|
||||
return goal->Type->BoolFlag[index].value;
|
||||
} else if ((s[0] == 's') && unit != NULL) { //spell type detected
|
||||
} else if (s[0] == 's') { //spell type detected
|
||||
Assert(goal->CurrentAction() == UnitActionSpellCast);
|
||||
const COrder_SpellCast &order = *static_cast<COrder_SpellCast *>(goal->CurrentOrder());
|
||||
const SpellType &spell = order.GetSpell();
|
||||
|
@ -201,11 +200,11 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (s[0] == 'p' && unit != NULL) { //player variable detected
|
||||
} else if (s[0] == 'p') { //player variable detected
|
||||
char *next = strchr(cur, '.');
|
||||
if (next == NULL) {
|
||||
fprintf(stderr, "Need also specify the %s player's property\n", cur);
|
||||
Exit(1);
|
||||
ExitFatal(1);
|
||||
} else {
|
||||
*next = '\0';
|
||||
}
|
||||
|
@ -213,7 +212,7 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
if (arg != NULL) {
|
||||
*arg = '\0';
|
||||
}
|
||||
return GetPlayerData(ParseAnimPlayer(*unit, cur), next + 1, arg + 1);
|
||||
return GetPlayerData(ParseAnimPlayer(unit, cur), next + 1, arg + 1);
|
||||
} else if (s[0] == 'r') { //random value
|
||||
char *next = strchr(cur, '.');
|
||||
if (next == NULL) {
|
||||
|
@ -224,12 +223,72 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
|
|||
return min + SyncRand(atoi(next + 1) - min + 1);
|
||||
}
|
||||
} else if (s[0] == 'l') { //player number
|
||||
return ParseAnimPlayer(*unit, cur);
|
||||
return ParseAnimPlayer(unit, cur);
|
||||
|
||||
}
|
||||
return atoi(parseint);
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse flags list in animation frame.
|
||||
**
|
||||
** @param unit Unit of the animation.
|
||||
** @param parseflag Flag list to parse.
|
||||
**
|
||||
** @return The parsed value.
|
||||
*/
|
||||
int ParseAnimFlags(const CUnit &unit, const char *parseflag)
|
||||
{
|
||||
char s[100];
|
||||
int flags = 0;
|
||||
|
||||
strcpy(s, parseflag);
|
||||
char *cur = s;
|
||||
char *next = s;
|
||||
while (next) {
|
||||
next = strchr(cur, '.');
|
||||
if (next) {
|
||||
*next = '\0';
|
||||
++next;
|
||||
}
|
||||
if (unit.Anim.Anim->Type == AnimationSpawnMissile) {
|
||||
if (!strcmp(cur, "none")) {
|
||||
flags = SM_None;
|
||||
return flags;
|
||||
} else if (!strcmp(cur, "damage")) {
|
||||
flags |= SM_Damage;
|
||||
} else if (!strcmp(cur, "totarget")) {
|
||||
flags |= SM_ToTarget;
|
||||
} else if (!strcmp(cur, "pixel")) {
|
||||
flags |= SM_Pixel;
|
||||
} else if (!strcmp(cur, "reltarget")) {
|
||||
flags |= SM_RelTarget;
|
||||
} else if (!strcmp(cur, "ranged")) {
|
||||
flags |= SM_Ranged;
|
||||
} else if (!strcmp(cur, "setdirection")) {
|
||||
flags |= SM_SetDirection;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown animation flag: %s\n", cur);
|
||||
ExitFatal(1);
|
||||
}
|
||||
} else if (unit.Anim.Anim->Type == AnimationSpawnUnit) {
|
||||
if (!strcmp(cur, "none")) {
|
||||
flags = SU_None;
|
||||
return flags;
|
||||
} else if (!strcmp(cur, "summoned")) {
|
||||
flags |= SU_Summoned;
|
||||
} else if (!strcmp(cur, "jointoai")) {
|
||||
flags |= SU_JoinToAIForce;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown animation flag: %s\n", cur);
|
||||
ExitFatal(1);
|
||||
}
|
||||
}
|
||||
cur = next;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Show unit animation.
|
||||
|
|
|
@ -52,7 +52,11 @@
|
|||
|
||||
int CAnimation_ExactFrame::ParseAnimInt(const CUnit *unit) const
|
||||
{
|
||||
return ::ParseAnimInt(unit, this->frame.c_str());
|
||||
if (unit == NULL) {
|
||||
return atoi(this->frame.c_str());
|
||||
} else {
|
||||
return ::ParseAnimInt(*unit, this->frame.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -53,7 +53,11 @@
|
|||
|
||||
int CAnimation_Frame::ParseAnimInt(const CUnit *unit) const
|
||||
{
|
||||
return ::ParseAnimInt(unit, this->frame.c_str());
|
||||
if (unit == NULL) {
|
||||
return atoi(this->frame.c_str());
|
||||
} else {
|
||||
return ::ParseAnimInt(*unit, this->frame.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -61,8 +61,8 @@ static bool returnFalse(int, int) { return false; }
|
|||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
const int lop = ParseAnimInt(&unit, this->leftVar.c_str());
|
||||
const int rop = ParseAnimInt(&unit, this->rightVar.c_str());
|
||||
const int lop = ParseAnimInt(unit, this->leftVar.c_str());
|
||||
const int rop = ParseAnimInt(unit, this->rightVar.c_str());
|
||||
const bool cond = this->binOpFunc(lop, rop);
|
||||
|
||||
if (cond) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
for (std::vector<std::string>::const_iterator it = cbArgs.begin(); it != cbArgs.end(); ++it) {
|
||||
const std::string str = *it;
|
||||
|
||||
const int arg = ParseAnimInt(&unit, str.c_str());
|
||||
const int arg = ParseAnimInt(unit, str.c_str());
|
||||
cb->pushInteger(arg);
|
||||
}
|
||||
cb->run();
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
Assert(unit.Anim.Anim == this);
|
||||
Assert(!move);
|
||||
|
||||
move = ParseAnimInt(&unit, this->moveStr.c_str());
|
||||
move = ParseAnimInt(unit, this->moveStr.c_str());
|
||||
}
|
||||
|
||||
/* virtual */ void CAnimation_Move::Init(const char *s, lua_State *)
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
if (SyncRand() % 100 < ParseAnimInt(&unit, this->randomStr.c_str())) {
|
||||
if (SyncRand() % 100 < ParseAnimInt(unit, this->randomStr.c_str())) {
|
||||
unit.Anim.Anim = this->gotoLabel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,9 +45,9 @@
|
|||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
if ((SyncRand() >> 8) & 1) {
|
||||
UnitRotate(unit, -ParseAnimInt(&unit, this->rotateStr.c_str()));
|
||||
UnitRotate(unit, -ParseAnimInt(unit, this->rotateStr.c_str()));
|
||||
} else {
|
||||
UnitRotate(unit, ParseAnimInt(&unit, this->rotateStr.c_str()));
|
||||
UnitRotate(unit, ParseAnimInt(unit, this->rotateStr.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
const int arg1 = ParseAnimInt(&unit, this->minWait.c_str());
|
||||
const int arg2 = ParseAnimInt(&unit, this->maxWait.c_str());
|
||||
const int arg1 = ParseAnimInt(unit, this->minWait.c_str());
|
||||
const int arg2 = ParseAnimInt(unit, this->maxWait.c_str());
|
||||
|
||||
unit.Anim.Wait = arg1 + SyncRand() % (arg2 - arg1 + 1);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ void UnitRotate(CUnit &unit, int rotate)
|
|||
const Vec2i pos = target.tilePos + target.Type->GetHalfTileSize() - unit.tilePos;
|
||||
UnitHeadingFromDeltaXY(unit, pos);
|
||||
} else {
|
||||
UnitRotate(unit, ParseAnimInt(&unit, this->rotateStr.c_str()));
|
||||
UnitRotate(unit, ParseAnimInt(unit, this->rotateStr.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,8 +178,8 @@ static void SetPlayerData(const int player, const char *prop, const char *arg, i
|
|||
|
||||
const char *var = this->varStr.c_str();
|
||||
const char *arg = this->argStr.c_str();
|
||||
const int playerId = ParseAnimInt(&unit, this->playerStr.c_str());
|
||||
int rop = ParseAnimInt(&unit, this->valueStr.c_str());
|
||||
const int playerId = ParseAnimInt(unit, this->playerStr.c_str());
|
||||
int rop = ParseAnimInt(unit, this->valueStr.c_str());
|
||||
int data = GetPlayerData(playerId, var, arg);
|
||||
|
||||
switch (this->mod) {
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
const int rop = ParseAnimInt(&unit, this->valueStr.c_str());
|
||||
const int rop = ParseAnimInt(unit, this->valueStr.c_str());
|
||||
int value = 0;
|
||||
if (!strcmp(next + 1, "Value")) {
|
||||
value = goal->Variable[index].Value;
|
||||
|
|
|
@ -46,68 +46,17 @@
|
|||
#include "pathfinder.h"
|
||||
#include "unit.h"
|
||||
|
||||
//SpawnMissile flags
|
||||
#define ANIM_SM_DAMAGE 1
|
||||
#define ANIM_SM_TOTARGET 2
|
||||
#define ANIM_SM_PIXEL 4
|
||||
#define ANIM_SM_RELTARGET 8
|
||||
#define ANIM_SM_RANGED 16
|
||||
#define ANIM_SM_SETDIRECTION 32
|
||||
|
||||
/**
|
||||
** Parse flags list in animation frame.
|
||||
**
|
||||
** @param unit Unit of the animation.
|
||||
** @param parseflag Flag list to parse.
|
||||
**
|
||||
** @return The parsed value.
|
||||
*/
|
||||
static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
||||
{
|
||||
char s[100];
|
||||
int flags = 0;
|
||||
|
||||
strcpy(s, parseflag);
|
||||
char *cur = s;
|
||||
char *next = s;
|
||||
while (next) {
|
||||
next = strchr(cur, '.');
|
||||
if (next) {
|
||||
*next = '\0';
|
||||
++next;
|
||||
}
|
||||
if (unit.Anim.Anim->Type == AnimationSpawnMissile) {
|
||||
if (!strcmp(cur, "damage")) {
|
||||
flags |= ANIM_SM_DAMAGE;
|
||||
} else if (!strcmp(cur, "totarget")) {
|
||||
flags |= ANIM_SM_TOTARGET;
|
||||
} else if (!strcmp(cur, "pixel")) {
|
||||
flags |= ANIM_SM_PIXEL;
|
||||
} else if (!strcmp(cur, "reltarget")) {
|
||||
flags |= ANIM_SM_RELTARGET;
|
||||
} else if (!strcmp(cur, "ranged")) {
|
||||
flags |= ANIM_SM_RANGED;
|
||||
} else if (!strcmp(cur, "setdirection")) {
|
||||
flags |= ANIM_SM_SETDIRECTION;
|
||||
}
|
||||
}
|
||||
cur = next;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ void CAnimation_SpawnMissile::Action(CUnit &unit, int &/*move*/, int /*scale*/) const
|
||||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
const int startx = ParseAnimInt(&unit, this->startXStr.c_str());
|
||||
const int starty = ParseAnimInt(&unit, this->startYStr.c_str());
|
||||
const int destx = ParseAnimInt(&unit, this->destXStr.c_str());
|
||||
const int desty = ParseAnimInt(&unit, this->destYStr.c_str());
|
||||
const int flags = ParseAnimFlags(unit, this->flagsStr.c_str());
|
||||
const int offsetnum = ParseAnimInt(&unit, this->offsetNumStr.c_str());
|
||||
const CUnit *goal = flags & ANIM_SM_RELTARGET ? unit.CurrentOrder()->GetGoal() : &unit;
|
||||
const int startx = ParseAnimInt(unit, this->startXStr.c_str());
|
||||
const int starty = ParseAnimInt(unit, this->startYStr.c_str());
|
||||
const int destx = ParseAnimInt(unit, this->destXStr.c_str());
|
||||
const int desty = ParseAnimInt(unit, this->destYStr.c_str());
|
||||
const SpawnMissile_Flags flags = (SpawnMissile_Flags)(ParseAnimFlags(unit, this->flagsStr.c_str()));
|
||||
const int offsetnum = ParseAnimInt(unit, this->offsetNumStr.c_str());
|
||||
const CUnit *goal = flags & SM_RelTarget ? unit.CurrentOrder()->GetGoal() : &unit;
|
||||
const int dir = ((goal->Direction + NextDirection / 2) & 0xFF) / NextDirection;
|
||||
const PixelPos moff = goal->Type->MissileOffsets[dir][!offsetnum ? 0 : offsetnum - 1];
|
||||
PixelPos start;
|
||||
|
@ -120,14 +69,14 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
if (!goal || goal->Destroyed) {
|
||||
return;
|
||||
}
|
||||
if ((flags & ANIM_SM_PIXEL)) {
|
||||
if ((flags & SM_Pixel)) {
|
||||
start.x = goal->tilePos.x * PixelTileSize.x + goal->IX + moff.x + startx;
|
||||
start.y = goal->tilePos.y * PixelTileSize.y + goal->IY + moff.y + starty;
|
||||
} else {
|
||||
start.x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2 + moff.x;
|
||||
start.y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2 + moff.y;
|
||||
}
|
||||
if ((flags & ANIM_SM_TOTARGET)) {
|
||||
if ((flags & SM_ToTarget)) {
|
||||
CUnit *target = goal->CurrentOrder()->GetGoal();
|
||||
if (!target || target->Destroyed) {
|
||||
Assert(!mtype->AlwaysFire || mtype->Range);
|
||||
|
@ -143,14 +92,14 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
COrder_SpellCast &order = *static_cast<COrder_SpellCast *>(goal->CurrentOrder());
|
||||
dest = Map.TilePosToMapPixelPos_Center(order.GetGoalPos());
|
||||
}
|
||||
if (flags & ANIM_SM_PIXEL) {
|
||||
if (flags & SM_Pixel) {
|
||||
dest.x += destx;
|
||||
dest.y += desty;
|
||||
} else {
|
||||
dest.x += destx * PixelTileSize.x;
|
||||
dest.y += desty * PixelTileSize.y;
|
||||
}
|
||||
} else if (flags & ANIM_SM_PIXEL) {
|
||||
} else if (flags & SM_Pixel) {
|
||||
dest.x = target->GetMapPixelPosCenter().x + destx;
|
||||
dest.y = target->GetMapPixelPosCenter().y + desty;
|
||||
} else {
|
||||
|
@ -159,7 +108,7 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
dest += target->Type->GetPixelSize() / 2;
|
||||
}
|
||||
} else {
|
||||
if ((flags & ANIM_SM_PIXEL)) {
|
||||
if ((flags & SM_Pixel)) {
|
||||
dest.x = goal->GetMapPixelPosCenter().x + destx;
|
||||
dest.y = goal->GetMapPixelPosCenter().y + desty;
|
||||
} else {
|
||||
|
@ -170,22 +119,22 @@ static int ParseAnimFlags(CUnit &unit, const char *parseflag)
|
|||
}
|
||||
Vec2i destTilePos = Map.MapPixelPosToTilePos(dest);
|
||||
const int dist = goal->MapDistanceTo(destTilePos);
|
||||
if ((flags & ANIM_SM_RANGED) && !(flags & ANIM_SM_PIXEL)
|
||||
if ((flags & SM_Ranged) && !(flags & SM_Pixel)
|
||||
&& dist > goal->Stats->Variables[ATTACKRANGE_INDEX].Max
|
||||
&& dist < goal->Type->MinAttackRange) {
|
||||
} else {
|
||||
Missile *missile = MakeMissile(*mtype, start, dest);
|
||||
if (flags & ANIM_SM_SETDIRECTION) {
|
||||
if (flags & SM_SetDirection) {
|
||||
PixelPos posd;
|
||||
posd.x = Heading2X[goal->Direction / NextDirection];
|
||||
posd.y = Heading2Y[goal->Direction / NextDirection];
|
||||
missile->MissileNewHeadingFromXY(posd);
|
||||
}
|
||||
if (flags & ANIM_SM_DAMAGE) {
|
||||
if (flags & SM_Damage) {
|
||||
missile->SourceUnit = &unit;
|
||||
}
|
||||
CUnit *target = goal->CurrentOrder()->GetGoal();
|
||||
if (flags & ANIM_SM_TOTARGET && target && target->IsAlive()) {
|
||||
if (flags & SM_ToTarget && target && target->IsAlive()) {
|
||||
missile->TargetUnit = target;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
|
||||
#include "animation/animation_spawnunit.h"
|
||||
|
||||
#include "../ai/ai_local.h"
|
||||
|
||||
#include "commands.h"
|
||||
#include "map.h"
|
||||
#include "unit.h"
|
||||
|
||||
|
@ -104,10 +107,12 @@ found:
|
|||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
|
||||
const int offX = ParseAnimInt(&unit, this->offXStr.c_str());
|
||||
const int offY = ParseAnimInt(&unit, this->offYStr.c_str());
|
||||
const int range = ParseAnimInt(&unit, this->rangeStr.c_str());
|
||||
const int playerId = ParseAnimInt(&unit, this->playerStr.c_str());
|
||||
const int offX = ParseAnimInt(unit, this->offXStr.c_str());
|
||||
const int offY = ParseAnimInt(unit, this->offYStr.c_str());
|
||||
const int range = ParseAnimInt(unit, this->rangeStr.c_str());
|
||||
const int playerId = ParseAnimInt(unit, this->playerStr.c_str());
|
||||
const SpawnUnit_Flags flags = (SpawnUnit_Flags)(ParseAnimFlags(unit, this->flagsStr.c_str()));
|
||||
|
||||
CPlayer &player = Players[playerId];
|
||||
const Vec2i pos(unit.tilePos.x + offX, unit.tilePos.y + offY);
|
||||
CUnitType *type = UnitTypeByIdent(this->unitTypeStr.c_str());
|
||||
|
@ -120,6 +125,17 @@ found:
|
|||
if (target != NULL) {
|
||||
target->tilePos = resPos;
|
||||
target->Place(resPos);
|
||||
if (flags & SU_Summoned) {
|
||||
target->Summoned = 1;
|
||||
}
|
||||
if ((flags & SU_JoinToAIForce) && unit.Player->AiEnabled) {
|
||||
int force = unit.Player->Ai->Force.GetForce(unit);
|
||||
if (force != -1) {
|
||||
unit.Player->Ai->Force[force].Insert(*target);
|
||||
target->GroupId = unit.GroupId;
|
||||
CommandDefend(*target, unit, FlushCommands);
|
||||
}
|
||||
}
|
||||
//DropOutOnSide(*target, LookingW, NULL);
|
||||
} else {
|
||||
DebugPrint("Unable to allocate Unit");
|
||||
|
@ -128,7 +144,7 @@ found:
|
|||
}
|
||||
|
||||
/*
|
||||
** s = "unitType offX offY range player"
|
||||
** s = "unitType offX offY range player flags"
|
||||
*/
|
||||
/* virtual */ void CAnimation_SpawnUnit::Init(const char *s, lua_State *)
|
||||
{
|
||||
|
@ -154,6 +170,10 @@ found:
|
|||
begin = std::min(len, str.find_first_not_of(' ', end));
|
||||
end = std::min(len, str.find(' ', begin));
|
||||
this->playerStr.assign(str, begin, end - begin);
|
||||
|
||||
begin = std::min(len, str.find_first_not_of(' ', end));
|
||||
end = std::min(len, str.find(' ', begin));
|
||||
this->flagsStr.assign(str, begin, end - begin);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
/* virtual */ void CAnimation_Wait::Action(CUnit &unit, int &/*move*/, int scale) const
|
||||
{
|
||||
Assert(unit.Anim.Anim == this);
|
||||
unit.Anim.Wait = ParseAnimInt(&unit, this->wait.c_str()) << scale >> 8;
|
||||
unit.Anim.Wait = ParseAnimInt(unit, this->wait.c_str()) << scale >> 8;
|
||||
if (unit.Variable[SLOW_INDEX].Value) { // unit is slowed down
|
||||
unit.Anim.Wait <<= 1;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,8 @@ extern int UnitShowAnimationScaled(CUnit &unit, const CAnimation *anim, int scal
|
|||
extern int UnitShowAnimation(CUnit &unit, const CAnimation *anim);
|
||||
|
||||
|
||||
extern int ParseAnimInt(const CUnit *unit, const char *parseint);
|
||||
extern int ParseAnimInt(const CUnit &unit, const char *parseint);
|
||||
extern int ParseAnimFlags(const CUnit &unit, const char *parseflag);
|
||||
|
||||
extern void FindLabelLater(CAnimation **anim, const std::string &name);
|
||||
|
||||
|
|
|
@ -35,6 +35,18 @@
|
|||
#include <string>
|
||||
#include "animation.h"
|
||||
|
||||
//SpawnMissile flags
|
||||
enum SpawnMissile_Flags {
|
||||
SM_None = 0, /// Clears all flags
|
||||
SM_Damage = 1, /// Missile deals damage to units
|
||||
SM_ToTarget = 2, /// Missile is directed to unit's target
|
||||
SM_Pixel = 4, /// Missile's offsets are calculated in pixels rather than tiles
|
||||
SM_RelTarget = 8, /// All calculations are relative to unit's target
|
||||
SM_Ranged = 16, /// Missile can't be shot if current range between unit and it's target
|
||||
/// is bigger than unit's attack range
|
||||
SM_SetDirection = 32 /// Missile takes the same direction as spawner
|
||||
};
|
||||
|
||||
class CAnimation_SpawnMissile : public CAnimation
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -35,6 +35,13 @@
|
|||
#include <string>
|
||||
#include "animation.h"
|
||||
|
||||
//SpawnUnit flags
|
||||
enum SpawnUnit_Flags {
|
||||
SU_None = 0, /// Clears all flags
|
||||
SU_Summoned = 1, /// Unit is marked as "summoned"
|
||||
SU_JoinToAIForce = 2 /// Unit is included into spawner's AI force, if available
|
||||
};
|
||||
|
||||
class CAnimation_SpawnUnit : public CAnimation
|
||||
{
|
||||
public:
|
||||
|
@ -49,6 +56,7 @@ private:
|
|||
std::string offYStr;
|
||||
std::string rangeStr;
|
||||
std::string playerStr;
|
||||
std::string flagsStr;
|
||||
};
|
||||
|
||||
//@}
|
||||
|
|
|
@ -339,21 +339,23 @@ public:
|
|||
int ResourcesHeld; /// Resources Held by a unit
|
||||
|
||||
unsigned char DamagedType; /// Index of damage type of unit which damaged this unit
|
||||
unsigned long Attacked; /// gamecycle unit was last attacked
|
||||
unsigned Blink : 3; /// Let selection rectangle blink
|
||||
unsigned Moving : 1; /// The unit is moving
|
||||
unsigned ReCast : 1; /// Recast again next cycle
|
||||
unsigned AutoRepair : 1; /// True if unit tries to repair on still action.
|
||||
unsigned long Attacked; /// gamecycle unit was last attacked
|
||||
unsigned Blink : 3; /// Let selection rectangle blink
|
||||
unsigned Moving : 1; /// The unit is moving
|
||||
unsigned ReCast : 1; /// Recast again next cycle
|
||||
unsigned AutoRepair : 1; /// True if unit tries to repair on still action.
|
||||
|
||||
unsigned Burning : 1; /// unit is burning
|
||||
unsigned Destroyed : 1; /// unit is destroyed pending reference
|
||||
unsigned Removed : 1; /// unit is removed (not on map)
|
||||
unsigned Selected : 1; /// unit is selected
|
||||
unsigned Burning : 1; /// unit is burning
|
||||
unsigned Destroyed : 1; /// unit is destroyed pending reference
|
||||
unsigned Removed : 1; /// unit is removed (not on map)
|
||||
unsigned Selected : 1; /// unit is selected
|
||||
|
||||
unsigned Constructed : 1; /// Unit is in construction
|
||||
unsigned Active : 1; /// Unit is active for AI
|
||||
unsigned Boarded : 1; /// Unit is on board a transporter.
|
||||
unsigned CacheLock : 1; /// Unit is on lock by unitcache operations.
|
||||
unsigned CacheLock : 1; /// Unit is on lock by unitcache operations.
|
||||
|
||||
unsigned Summoned : 1; /// Unit is summoned using spells.
|
||||
|
||||
unsigned TeamSelected; /// unit is selected by a team member.
|
||||
CPlayer *RescuedFrom; /// The original owner of a rescued unit.
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
} else {
|
||||
portal = MakeUnitAndPlace(goalPos, *this->PortalType,
|
||||
CurrentPlayer ? caster.Player : &Players[PlayerNumNeutral]);
|
||||
portal->Summoned = 1;
|
||||
}
|
||||
portal->TTL = GameCycle + this->TTL;
|
||||
// Goal is used to link to destination circle of power
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include "spell/spell_summon.h"
|
||||
|
||||
#include "../ai/ai_local.h"
|
||||
|
||||
#include "actions.h"
|
||||
#include "commands.h"
|
||||
#include "script.h"
|
||||
|
@ -124,6 +126,8 @@ public:
|
|||
if (target != NULL) {
|
||||
target->tilePos = pos;
|
||||
DropOutOnSide(*target, LookingW, NULL);
|
||||
// To avoid defending summoned unit for AI
|
||||
target->Summoned = 1;
|
||||
//
|
||||
// set life span. ttl=0 results in a permanent unit.
|
||||
//
|
||||
|
@ -131,13 +135,13 @@ public:
|
|||
target->TTL = GameCycle + ttl;
|
||||
}
|
||||
|
||||
// To avoid defending summoned unit for AI
|
||||
// Insert summoned unit to AI force so it will help them in battle
|
||||
if (caster.Player->AiEnabled) {
|
||||
if (caster.GroupId) {
|
||||
int force = caster.Player->Ai->Force.GetForce(caster);
|
||||
if (force != -1) {
|
||||
caster.Player->Ai->Force[force].Insert(*target);
|
||||
target->GroupId = caster.GroupId;
|
||||
CommandDefend(*target, caster, FlushCommands);
|
||||
} else {
|
||||
target->GroupId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -377,6 +377,9 @@ static int CclUnit(lua_State *l)
|
|||
} else if (!strcmp(value, "selected")) {
|
||||
unit->Selected = 1;
|
||||
--j;
|
||||
} else if (!strcmp(value, "summoned")) {
|
||||
unit->Summoned = 1;
|
||||
--j;
|
||||
} else if (!strcmp(value, "rescued-from")) {
|
||||
unit->RescuedFrom = &Players[LuaToNumber(l, 2, j + 1)];
|
||||
} else if (!strcmp(value, "seen-by-player")) {
|
||||
|
|
|
@ -453,6 +453,7 @@ void CUnit::Init()
|
|||
Moving = 0;
|
||||
ReCast = 0;
|
||||
CacheLock = 0;
|
||||
Summoned = 0;
|
||||
memset(&Anim, 0, sizeof(Anim));
|
||||
CurrentResource = 0;
|
||||
Orders.clear();
|
||||
|
|
|
@ -177,6 +177,9 @@ void SaveUnit(const CUnit &unit, CFile &file)
|
|||
if (unit.Selected) {
|
||||
file.printf(" \"selected\",");
|
||||
}
|
||||
if (unit.Summoned) {
|
||||
file.printf(" \"summoned\",");
|
||||
}
|
||||
if (unit.RescuedFrom) {
|
||||
file.printf(" \"rescued-from\", %d,", unit.RescuedFrom->Index);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue