Some clean up with Missile :
- use ref - use PixelPos instead of x, y
This commit is contained in:
parent
006cba3793
commit
1d66191f8d
12 changed files with 265 additions and 324 deletions
src
action
game
include
map
sound
stratagus
ui
unit
|
@ -1086,7 +1086,8 @@ int UnitShowAnimationScaled(CUnit &unit, const CAnimation *anim, int scale)
|
|||
const int desty = ParseAnimInt(&unit, unit.Anim.Anim->D.SpawnMissile.DestY);
|
||||
const int flags = ParseAnimFlags(unit, unit.Anim.Anim->D.SpawnMissile.Flags);
|
||||
CUnit *goal;
|
||||
int x, y, dx, dy;
|
||||
PixelPos start;
|
||||
PixelPos dest;
|
||||
|
||||
if ((flags & ANIM_SM_RELTARGET) && unit.CurrentOrder()->HasGoal()) {
|
||||
goal = unit.CurrentOrder()->GetGoal();
|
||||
|
@ -1094,37 +1095,37 @@ int UnitShowAnimationScaled(CUnit &unit, const CAnimation *anim, int scale)
|
|||
goal = &unit;
|
||||
}
|
||||
if ((flags & ANIM_SM_PIXEL)) {
|
||||
x = goal->tilePos.x * PixelTileSize.x + goal->IX + startx;
|
||||
y = goal->tilePos.y * PixelTileSize.y + goal->IY + starty;
|
||||
start.x = goal->tilePos.x * PixelTileSize.x + goal->IX + startx;
|
||||
start.y = goal->tilePos.y * PixelTileSize.y + goal->IY + starty;
|
||||
} else {
|
||||
x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
start.x = (goal->tilePos.x + startx) * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
start.y = (goal->tilePos.y + starty) * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
}
|
||||
if ((flags & ANIM_SM_TOTARGET) && goal->CurrentOrder()->HasGoal()) {
|
||||
CUnit &target = *goal->CurrentOrder()->GetGoal();
|
||||
|
||||
if (flags & ANIM_SM_PIXEL) {
|
||||
dx = target.tilePos.x * PixelTileSize.x + target.IX;
|
||||
dy = target.tilePos.y * PixelTileSize.y + target.IY;
|
||||
dest.x = target.tilePos.x * PixelTileSize.x + target.IX;
|
||||
dest.y = target.tilePos.y * PixelTileSize.y + target.IY;
|
||||
} else {
|
||||
dx = target.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
dy = target.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
dest.x = target.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
dest.y = target.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
}
|
||||
} else {
|
||||
if ((flags & ANIM_SM_PIXEL)) {
|
||||
dx = goal->tilePos.x * PixelTileSize.x + goal->IX + destx;
|
||||
dy = goal->tilePos.y * PixelTileSize.y + goal->IY + desty;
|
||||
dest.x = goal->tilePos.x * PixelTileSize.x + goal->IX + destx;
|
||||
dest.y = goal->tilePos.y * PixelTileSize.y + goal->IY + desty;
|
||||
} else {
|
||||
dx = (unit.tilePos.x + destx) * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
dy = (unit.tilePos.y + desty) * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
dest.x = (unit.tilePos.x + destx) * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
dest.y = (unit.tilePos.y + desty) * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
}
|
||||
}
|
||||
const int dist = goal->MapDistanceTo(dx, dy);
|
||||
const int dist = goal->MapDistanceTo(dest.x, dest.y);
|
||||
if ((flags & ANIM_SM_RANGED) && !(flags & ANIM_SM_PIXEL)
|
||||
&& dist > goal->Stats->Variables[ATTACKRANGE_INDEX].Max
|
||||
&& dist < goal->Type->MinAttackRange) {
|
||||
} else {
|
||||
Missile *missile = MakeMissile(MissileTypeByIdent(unit.Anim.Anim->D.SpawnMissile.Missile), x, y, dx, dy);
|
||||
Missile *missile = MakeMissile(*MissileTypeByIdent(unit.Anim.Anim->D.SpawnMissile.Missile), start, dest);
|
||||
if (flags & ANIM_SM_DAMAGE) {
|
||||
missile->SourceUnit = &unit;
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ int SaveGame(const std::string &filename)
|
|||
SaveAi(&file);
|
||||
SaveSelections(&file);
|
||||
SaveGroups(&file);
|
||||
SaveMissiles(&file);
|
||||
SaveMissiles(file);
|
||||
SaveReplayList(&file);
|
||||
// FIXME: find all state information which must be saved.
|
||||
s = SaveGlobal(Lua, true);
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
**
|
||||
** Class of the missile-type, defines the basic effects of the
|
||||
** missile. Look at the different class identifiers for more
|
||||
** informations (::_missile_class_, ::MissileClassNone, ...).
|
||||
** informations (::MissileClassNone, ...).
|
||||
**
|
||||
** MissileType::NumBounces
|
||||
**
|
||||
|
@ -334,48 +334,27 @@ class LuaCallback;
|
|||
#define MAX_MISSILES 2048 /// maximum number of missiles
|
||||
#define MAX_LOCAL_MISSILES 4096 /// maximum number of local missiles
|
||||
|
||||
/**
|
||||
** Missile-type-class typedef
|
||||
*/
|
||||
typedef int MissileClass;
|
||||
|
||||
/**
|
||||
** Missile-class this defines how a missile-type reacts.
|
||||
**
|
||||
*/
|
||||
enum _missile_class_ {
|
||||
/// Missile does nothing
|
||||
MissileClassNone,
|
||||
/// Missile flies from x,y to x1,y1
|
||||
MissileClassPointToPoint,
|
||||
/// Missile flies from x,y to x1,y1 than shows hit animation.
|
||||
MissileClassPointToPointWithHit,
|
||||
/// Missile flies from x,y to x1,y1 and animates ONCE from start to finish and back
|
||||
MissileClassPointToPointCycleOnce,
|
||||
/// Missile flies from x,y to x1,y1 than bounces three times.
|
||||
MissileClassPointToPointBounce,
|
||||
/// Missile appears at x,y, does it's anim and vanishes.
|
||||
MissileClassStay,
|
||||
/// Missile appears at x,y, then cycle through the frames once.
|
||||
MissileClassCycleOnce,
|
||||
/// Missile doesn't move, than checks the source unit for HP.
|
||||
MissileClassFire,
|
||||
/// Missile shows the hit points.
|
||||
MissileClassHit,
|
||||
/// Missile flies from x,y to x1,y1 using a parabolic path
|
||||
MissileClassParabolic,
|
||||
/// Missile wait on x,y until a non-air unit comes by, the explodes.
|
||||
MissileClassLandMine,
|
||||
/// Missile appears at x,y, is whirlwind
|
||||
MissileClassWhirlwind,
|
||||
/// Missile surround x,y
|
||||
MissileClassFlameShield,
|
||||
/// Missile is death coil.
|
||||
MissileClassDeathCoil,
|
||||
/// Missile seeks towards to target unit
|
||||
MissileClassTracer,
|
||||
/// Missile remains clipped to target's current goal and plays his animation once
|
||||
MissileClassClipToTarget
|
||||
enum {
|
||||
MissileClassNone, /// Missile does nothing
|
||||
MissileClassPointToPoint, /// Missile flies from x,y to x1,y1
|
||||
MissileClassPointToPointWithHit, /// Missile flies from x,y to x1,y1 than shows hit animation.
|
||||
MissileClassPointToPointCycleOnce, /// Missile flies from x,y to x1,y1 and animates ONCE from start to finish and back
|
||||
MissileClassPointToPointBounce, /// Missile flies from x,y to x1,y1 than bounces three times.
|
||||
MissileClassStay, /// Missile appears at x,y, does it's anim and vanishes.
|
||||
MissileClassCycleOnce, /// Missile appears at x,y, then cycle through the frames once.
|
||||
MissileClassFire, /// Missile doesn't move, than checks the source unit for HP.
|
||||
MissileClassHit, /// Missile shows the hit points.
|
||||
MissileClassParabolic, /// Missile flies from x,y to x1,y1 using a parabolic path
|
||||
MissileClassLandMine, /// Missile wait on x,y until a non-air unit comes by, the explodes.
|
||||
MissileClassWhirlwind, /// Missile appears at x,y, is whirlwind
|
||||
MissileClassFlameShield, /// Missile surround x,y
|
||||
MissileClassDeathCoil, /// Missile is death coil.
|
||||
MissileClassTracer, /// Missile seeks towards to target unit
|
||||
MissileClassClipToTarget /// Missile remains clipped to target's current goal and plays his animation once
|
||||
};
|
||||
|
||||
/// Base structure of missile-types
|
||||
|
@ -388,15 +367,11 @@ public:
|
|||
void LoadMissileSprite();
|
||||
void Init();
|
||||
void DrawMissileType(int frame, const PixelPos &pos) const;
|
||||
void DrawMissileType(int frame, int x, int y) const {
|
||||
PixelPos pos = {x, y};
|
||||
|
||||
DrawMissileType(frame, pos);
|
||||
}
|
||||
|
||||
int Width() const { return size.x; }
|
||||
int Height() const { return size.y; }
|
||||
|
||||
//private:
|
||||
std::string Ident; /// missile name
|
||||
int Transparency; /// missile transparency
|
||||
PixelSize size; /// missile size in pixels
|
||||
|
@ -413,7 +388,7 @@ public:
|
|||
bool CanHitOwner; /// missile can hit the owner
|
||||
bool FriendlyFire; /// missile can't hit own units
|
||||
|
||||
MissileClass Class; /// missile class
|
||||
int Class; /// missile class
|
||||
int NumBounces; /// number of bounces
|
||||
int StartDelay; /// missile start delay
|
||||
int Sleep; /// missile sleep
|
||||
|
@ -436,30 +411,25 @@ public:
|
|||
----------------------------------------------------------------------------*/
|
||||
|
||||
/// Missile on the map
|
||||
class Missile {
|
||||
class Missile
|
||||
{
|
||||
protected:
|
||||
Missile();
|
||||
|
||||
public:
|
||||
virtual ~Missile() {};
|
||||
|
||||
static Missile *Init(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
static Missile *Init(MissileType *mtype, int sx, int sy, int dx, int dy) {
|
||||
PixelPos startPos = {sx, sy};
|
||||
PixelPos destPos = {dx, dy};
|
||||
|
||||
return Init(mtype, startPos, destPos);
|
||||
}
|
||||
static Missile *Init(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
|
||||
virtual void Action() = 0;
|
||||
|
||||
void DrawMissile(const CViewport *vp) const;
|
||||
void SaveMissile(CFile *file) const;
|
||||
void DrawMissile(const CViewport &vp) const;
|
||||
void SaveMissile(CFile &file) const;
|
||||
|
||||
PixelPos source; /// Missile source position
|
||||
PixelPos position; /// missile pixel position
|
||||
PixelPos destination; /// missile pixel destination
|
||||
MissileType *Type; /// missile-type pointer
|
||||
const MissileType *Type; /// missile-type pointer
|
||||
int SpriteFrame; /// sprite frame counter
|
||||
int State; /// state
|
||||
int AnimWait; /// Animation wait.
|
||||
|
@ -484,20 +454,19 @@ public:
|
|||
static unsigned int Count; /// slot number generator.
|
||||
};
|
||||
|
||||
struct MissileDrawProxy
|
||||
class MissileDrawProxy
|
||||
{
|
||||
MissileType *Type; /// missile-type pointer
|
||||
public:
|
||||
void DrawMissile(const CViewport &vp) const;
|
||||
|
||||
void operator=(const Missile* missile);
|
||||
public:
|
||||
const MissileType *Type; /// missile-type pointer
|
||||
union {
|
||||
int Damage; /// direct damage that missile applies
|
||||
int SpriteFrame; /// sprite frame counter
|
||||
} data;
|
||||
short X;
|
||||
short Y;
|
||||
|
||||
void DrawMissile(const CViewport *vp) const;
|
||||
|
||||
void operator=(const Missile* missile);
|
||||
|
||||
PixelPos pixelPos;
|
||||
};
|
||||
|
||||
class MissileNone : public Missile {
|
||||
|
@ -599,40 +568,26 @@ extern MissileType *NewMissileTypeSlot(const std::string& ident);
|
|||
/// Get missile-type by ident
|
||||
extern MissileType *MissileTypeByIdent(const std::string& ident);
|
||||
/// create a missile
|
||||
extern Missile *MakeMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
inline Missile *MakeMissile(MissileType *mtype, int sx, int sy, int dx, int dy) {
|
||||
const PixelPos startPos = {sx, sy};
|
||||
const PixelPos destPos = {dx, dy};
|
||||
|
||||
return MakeMissile(mtype, startPos, destPos);
|
||||
}
|
||||
extern Missile *MakeMissile(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
/// create a local missile
|
||||
extern Missile *MakeLocalMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
inline Missile *MakeLocalMissile(MissileType *mtype, int sx, int sy, int dx, int dy) {
|
||||
const PixelPos startPos = {sx, sy};
|
||||
const PixelPos destPos = {dx, dy};
|
||||
|
||||
return MakeLocalMissile(mtype, startPos, destPos);
|
||||
}
|
||||
extern Missile *MakeLocalMissile(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos);
|
||||
|
||||
/// fire a missile
|
||||
extern void FireMissile(CUnit &unit);
|
||||
|
||||
extern int FindAndSortMissiles(const CViewport *vp,
|
||||
Missile *table[], const int tablesize);
|
||||
extern int FindAndSortMissiles(const CViewport *vp,
|
||||
MissileDrawProxy table[], const int tablesize);
|
||||
extern int FindAndSortMissiles(const CViewport &vp, Missile *table[], const int tablesize);
|
||||
extern int FindAndSortMissiles(const CViewport &vp, MissileDrawProxy table[], const int tablesize);
|
||||
|
||||
/// handle all missiles
|
||||
extern void MissileActions();
|
||||
/// distance from view point to missile
|
||||
extern int ViewPointDistanceToMissile(const Missile *missile);
|
||||
extern int ViewPointDistanceToMissile(const Missile &missile);
|
||||
|
||||
/// Get the burning building missile based on hp percent
|
||||
extern MissileType *MissileBurningBuilding(int percent);
|
||||
|
||||
/// Save missiles
|
||||
extern void SaveMissiles(CFile *file);
|
||||
extern void SaveMissiles(CFile &file);
|
||||
|
||||
/// Initialize missile-types
|
||||
extern void InitMissileTypes();
|
||||
|
|
|
@ -182,6 +182,11 @@ public:
|
|||
/// Convert map pixel coordinates into viewport coordinates
|
||||
void MapPixel2Viewport(int &x, int &y) const;
|
||||
|
||||
// Convert screen coordinates into map pixel coordinates
|
||||
PixelPos ScreenToMapPixelPos(const PixelPos& screenPixelPos) const;
|
||||
// Convert map pixel coordinates into screen coordinates
|
||||
PixelPos MapToScreenPixelPos(const PixelPos& mapPixelPos) const;
|
||||
|
||||
/// Set the current map view to x,y(upper,left corner)
|
||||
void Set(int x, int y, int offsetx, int offsety);
|
||||
/// Center map on point in viewport
|
||||
|
|
|
@ -768,6 +768,8 @@ public:
|
|||
bool CanMove() const { return Type->CanMove(); }
|
||||
|
||||
int GetDrawLevel() const;
|
||||
|
||||
PixelPos GetMapPixelPosCenter() const;
|
||||
};
|
||||
|
||||
typedef COrder* COrderPtr;
|
||||
|
@ -1011,6 +1013,8 @@ extern void UpdateForNewUnit(const CUnit &unit, int upgrade);
|
|||
/// @todo more docu
|
||||
extern void NearestOfUnit(const CUnit &unit, const Vec2i& pos, Vec2i *dpos);
|
||||
|
||||
extern CUnit *GetFirstContainer(const CUnit &unit);
|
||||
|
||||
/// Call when an Unit goes under fog.
|
||||
extern void UnitGoesUnderFog(CUnit &unit, const CPlayer &player);
|
||||
/// Call when an Unit goes out of fog.
|
||||
|
|
|
@ -163,6 +163,27 @@ void CViewport::MapPixel2Viewport(int &x, int &y) const
|
|||
y = y + this->Y - (this->MapY * PixelTileSize.y + this->OffsetY);
|
||||
}
|
||||
|
||||
// Convert viewport coordinates into map pixel coordinates
|
||||
PixelPos CViewport::ScreenToMapPixelPos(const PixelPos &screenPixelPos) const
|
||||
{
|
||||
const int x = (screenPixelPos.x - this->X + this->MapX * PixelTileSize.x + this->OffsetX);
|
||||
const int y = (screenPixelPos.y - this->Y + this->MapY * PixelTileSize.y + this->OffsetY);
|
||||
const PixelPos mapPixelPos = {x, y};
|
||||
|
||||
return mapPixelPos;
|
||||
}
|
||||
|
||||
// Convert map pixel coordinates into viewport coordinates
|
||||
PixelPos CViewport::MapToScreenPixelPos(const PixelPos &mapPixelPos) const
|
||||
{
|
||||
PixelPos screenPixelPos = {
|
||||
mapPixelPos.x + this->X - (this->MapX * PixelTileSize.x + this->OffsetX),
|
||||
mapPixelPos.y + this->Y - (this->MapY * PixelTileSize.y + this->OffsetY)
|
||||
};
|
||||
return screenPixelPos;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
** Change viewpoint of map viewport v to x,y.
|
||||
**
|
||||
|
@ -341,7 +362,7 @@ public:
|
|||
//
|
||||
if (lock.TryLock()) {
|
||||
nunits = FindAndSortUnits(vp, unittable);
|
||||
nmissiles = FindAndSortMissiles(vp, missiletable, MAX_MISSILES * 9);
|
||||
nmissiles = FindAndSortMissiles(*vp, missiletable, MAX_MISSILES * 9);
|
||||
lock.UnLock();
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +376,7 @@ public:
|
|||
unittable[i].Draw(vp);
|
||||
++i;
|
||||
} else {
|
||||
missiletable[j].DrawMissile(vp);
|
||||
missiletable[j].DrawMissile(*vp);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +384,7 @@ public:
|
|||
unittable[i].Draw(vp);
|
||||
}
|
||||
for (; j < nmissiles; ++j) {
|
||||
missiletable[j].DrawMissile(vp);
|
||||
missiletable[j].DrawMissile(*vp);
|
||||
}
|
||||
lock.UnLock();
|
||||
}
|
||||
|
@ -406,7 +427,7 @@ void CViewport::Draw() const
|
|||
// We find and sort units after draw level.
|
||||
//
|
||||
int nunits = FindAndSortUnits(this, unittable);
|
||||
int nmissiles = FindAndSortMissiles(this, missiletable, MAX_MISSILES * 9);
|
||||
int nmissiles = FindAndSortMissiles(*this, missiletable, MAX_MISSILES * 9);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
|
@ -415,7 +436,7 @@ void CViewport::Draw() const
|
|||
unittable[i]->Draw(this);
|
||||
++i;
|
||||
} else {
|
||||
missiletable[j]->DrawMissile(this);
|
||||
missiletable[j]->DrawMissile(*this);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +444,7 @@ void CViewport::Draw() const
|
|||
unittable[i]->Draw(this);
|
||||
}
|
||||
for (; j < nmissiles; ++j) {
|
||||
missiletable[j]->DrawMissile(this);
|
||||
missiletable[j]->DrawMissile(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -334,7 +334,7 @@ void PlayMissileSound(const Missile *missile, CSound *sound)
|
|||
if (channel == -1) {
|
||||
return;
|
||||
}
|
||||
SetChannelVolume(channel, CalculateVolume(false, ViewPointDistanceToMissile(missile), sound->Range));
|
||||
SetChannelVolume(channel, CalculateVolume(false, ViewPointDistanceToMissile(*missile), sound->Range));
|
||||
SetChannelStereo(channel, stereo);
|
||||
}
|
||||
|
||||
|
|
|
@ -169,11 +169,11 @@ Missile::Missile() :
|
|||
**
|
||||
** @return created missile.
|
||||
*/
|
||||
Missile *Missile::Init(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
/* static */ Missile *Missile::Init(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
{
|
||||
Missile *missile = NULL;
|
||||
|
||||
switch (mtype->Class) {
|
||||
switch (mtype.Class) {
|
||||
case MissileClassNone :
|
||||
missile = new MissileNone;
|
||||
break;
|
||||
|
@ -223,13 +223,13 @@ Missile *Missile::Init(MissileType *mtype, const PixelPos &startPos, const Pixel
|
|||
missile = new MissileClipToTarget;
|
||||
break;
|
||||
}
|
||||
const PixelPos halfSize = mtype->size / 2;
|
||||
const PixelPos halfSize = mtype.size / 2;
|
||||
missile->position = startPos - halfSize;
|
||||
missile->destination = destPos - halfSize;
|
||||
missile->source = missile->position;
|
||||
missile->Type = mtype;
|
||||
missile->Wait = mtype->Sleep;
|
||||
missile->Delay = mtype->StartDelay;
|
||||
missile->Type = &mtype;
|
||||
missile->Wait = mtype.Sleep;
|
||||
missile->Delay = mtype.StartDelay;
|
||||
|
||||
return missile;
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ Missile *Missile::Init(MissileType *mtype, const PixelPos &startPos, const Pixel
|
|||
**
|
||||
** @return created missile.
|
||||
*/
|
||||
Missile *MakeMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
Missile *MakeMissile(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
{
|
||||
Missile *missile = Missile::Init(mtype, startPos, destPos);
|
||||
|
||||
|
@ -260,7 +260,7 @@ Missile *MakeMissile(MissileType *mtype, const PixelPos &startPos, const PixelPo
|
|||
**
|
||||
** @return created missile.
|
||||
*/
|
||||
Missile *MakeLocalMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
Missile *MakeLocalMissile(const MissileType &mtype, const PixelPos &startPos, const PixelPos &destPos)
|
||||
{
|
||||
Missile *missile = Missile::Init(mtype, startPos, destPos);
|
||||
|
||||
|
@ -356,6 +356,19 @@ static int CalculateDamage(const CUnit &attacker, const CUnit &goal)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Get pixel position of the center of the specified tilePos.
|
||||
*/
|
||||
static PixelPos GetPixelPosFromCenterTile(const Vec2i& tilePos)
|
||||
{
|
||||
PixelPos pixelPos = {tilePos.x * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
tilePos.y * PixelTileSize.y + PixelTileSize.y / 2};
|
||||
|
||||
return pixelPos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Fire missile.
|
||||
**
|
||||
|
@ -363,17 +376,11 @@ static int CalculateDamage(const CUnit &attacker, const CUnit &goal)
|
|||
*/
|
||||
void FireMissile(CUnit &unit)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
CUnit *goal = unit.CurrentOrder()->GetGoal();
|
||||
|
||||
//
|
||||
// Goal dead?
|
||||
//
|
||||
if (goal) {
|
||||
|
||||
// Better let the caller/action handle this.
|
||||
|
||||
if (goal->Destroyed) {
|
||||
DebugPrint("destroyed unit\n");
|
||||
return;
|
||||
|
@ -381,14 +388,11 @@ void FireMissile(CUnit &unit)
|
|||
if (goal->Removed || goal->CurrentAction() == UnitActionDie) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Some missile hit the field of the target and all units on it.
|
||||
// FIXME: goal is already dead, but missile could hit others?
|
||||
}
|
||||
|
||||
//
|
||||
// No missile hits immediately!
|
||||
//
|
||||
if (unit.Type->Missile.Missile->Class == MissileClassNone) {
|
||||
// No goal, take target coordinates
|
||||
if (!goal) {
|
||||
|
@ -414,20 +418,14 @@ void FireMissile(CUnit &unit)
|
|||
}
|
||||
|
||||
// If Firing from inside a Bunker
|
||||
if (unit.Container) {
|
||||
x = unit.Container->tilePos.x * PixelTileSize.x + PixelTileSize.x / 2; // missile starts in tile middle
|
||||
y = unit.Container->tilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
} else {
|
||||
x = unit.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2; // missile starts in tile middle
|
||||
y = unit.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
}
|
||||
CUnit* from = GetFirstContainer(unit);
|
||||
const PixelPos startPixelPos = GetPixelPosFromCenterTile(from->tilePos);
|
||||
|
||||
Vec2i dpos;
|
||||
if (goal) {
|
||||
Assert(goal->Type); // Target invalid?
|
||||
//
|
||||
// Moved out of attack range?
|
||||
//
|
||||
|
||||
if (unit.MapDistanceTo(*goal) < unit.Type->MinAttackRange) {
|
||||
DebugPrint("Missile target too near %d,%d\n" _C_
|
||||
unit.MapDistanceTo(*goal) _C_ unit.Type->MinAttackRange);
|
||||
|
@ -436,20 +434,14 @@ void FireMissile(CUnit &unit)
|
|||
}
|
||||
// Fire to nearest point of the unit!
|
||||
// If Firing from inside a Bunker
|
||||
if (unit.Container) {
|
||||
NearestOfUnit(*goal, unit.Container->tilePos, &dpos);
|
||||
} else {
|
||||
NearestOfUnit(*goal, unit.tilePos, &dpos);
|
||||
}
|
||||
NearestOfUnit(*goal, GetFirstContainer(unit)->tilePos, &dpos);
|
||||
} else {
|
||||
dpos = unit.CurrentOrder()->goalPos;
|
||||
// FIXME: Can this be too near??
|
||||
}
|
||||
|
||||
// Fire to the tile center of the destination.
|
||||
dpos.x = dpos.x * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
dpos.y = dpos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
Missile *missile = MakeMissile(unit.Type->Missile.Missile, x, y, dpos.x, dpos.y);
|
||||
const PixelPos destPixelPos = GetPixelPosFromCenterTile(dpos);
|
||||
Missile *missile = MakeMissile(*unit.Type->Missile.Missile, startPixelPos, destPixelPos);
|
||||
//
|
||||
// Damage of missile
|
||||
//
|
||||
|
@ -556,25 +548,23 @@ void MissileType::DrawMissileType(int frame, const PixelPos &pos) const
|
|||
}
|
||||
}
|
||||
|
||||
void MissileDrawProxy::DrawMissile(const CViewport *vp) const
|
||||
void MissileDrawProxy::DrawMissile(const CViewport &vp) const
|
||||
{
|
||||
const int x = this->X - vp->MapX * PixelTileSize.x + vp->X - vp->OffsetX;
|
||||
const int y = this->Y - vp->MapY * PixelTileSize.y + vp->Y - vp->OffsetY;
|
||||
const PixelPos sceenPixelPos = vp.MapToScreenPixelPos(this->pixelPos);
|
||||
|
||||
switch (this->Type->Class) {
|
||||
case MissileClassHit:
|
||||
CLabel(GetGameFont()).DrawClip(x,y, this->data.Damage);
|
||||
//VideoDrawNumberClip(x, y, GetGameFont(), this->data.Damage);
|
||||
CLabel(GetGameFont()).DrawClip(sceenPixelPos.x, sceenPixelPos.y, this->data.Damage);
|
||||
break;
|
||||
default:
|
||||
this->Type->DrawMissileType(this->data.SpriteFrame, x, y);
|
||||
this->Type->DrawMissileType(this->data.SpriteFrame, sceenPixelPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MissileDrawProxy::operator=(const Missile* missile) {
|
||||
this->Type = missile->Type;
|
||||
this->X = missile->position.x;
|
||||
this->Y = missile->position.y;
|
||||
this->pixelPos = missile->position;
|
||||
if (missile->Type->Class == MissileClassHit) {
|
||||
this->data.Damage = missile->Damage;
|
||||
} else {
|
||||
|
@ -585,7 +575,7 @@ void MissileDrawProxy::operator=(const Missile* missile) {
|
|||
/**
|
||||
** Draw missile.
|
||||
*/
|
||||
void Missile::DrawMissile(const CViewport *vp) const
|
||||
void Missile::DrawMissile(const CViewport &vp) const
|
||||
{
|
||||
Assert(this->Type);
|
||||
|
||||
|
@ -597,20 +587,19 @@ void Missile::DrawMissile(const CViewport *vp) const
|
|||
}
|
||||
#endif
|
||||
}
|
||||
const int x = this->position.x - vp->MapX * PixelTileSize.x + vp->X - vp->OffsetX;
|
||||
const int y = this->position.y - vp->MapY * PixelTileSize.y + vp->Y - vp->OffsetY;
|
||||
const PixelPos screenPixelPos = vp.MapToScreenPixelPos(this->position);
|
||||
|
||||
switch (this->Type->Class) {
|
||||
case MissileClassHit:
|
||||
CLabel(GetGameFont()).DrawClip(x, y, this->Damage);
|
||||
CLabel(GetGameFont()).DrawClip(screenPixelPos.x, screenPixelPos.y, this->Damage);
|
||||
break;
|
||||
default:
|
||||
this->Type->DrawMissileType(this->SpriteFrame, x, y);
|
||||
this->Type->DrawMissileType(this->SpriteFrame, screenPixelPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool MissileDrawLevelCompare(const Missile*const l,
|
||||
const Missile*const r)
|
||||
static bool MissileDrawLevelCompare(const Missile*const l, const Missile*const r)
|
||||
{
|
||||
if (l->Type->DrawLevel == r->Type->DrawLevel) {
|
||||
return l->Slot < r->Slot;
|
||||
|
@ -628,22 +617,19 @@ static bool MissileDrawLevelCompare(const Missile*const l,
|
|||
**
|
||||
** @return number of missiles returned in table
|
||||
*/
|
||||
int FindAndSortMissiles(const CViewport *vp,
|
||||
Missile *table[], const int tablesize)
|
||||
int FindAndSortMissiles(const CViewport &vp, Missile *table[], const int tablesize)
|
||||
{
|
||||
int nmissiles = 0;
|
||||
std::vector<Missile *>::const_iterator i;
|
||||
|
||||
//
|
||||
// Loop through global missiles, then through locals.
|
||||
//
|
||||
for (i = GlobalMissiles.begin(); i != GlobalMissiles.end() && nmissiles < tablesize; ++i) {
|
||||
Missile &missile = *(*i);
|
||||
if (missile.Delay || missile.Hidden) {
|
||||
continue; // delayed or hidden -> aren't shown
|
||||
}
|
||||
// Draw only visible missiles
|
||||
if (MissileVisibleInViewport(*vp, missile)) {
|
||||
if (MissileVisibleInViewport(vp, missile)) {
|
||||
table[nmissiles++] = &missile;
|
||||
}
|
||||
}
|
||||
|
@ -662,19 +648,15 @@ int FindAndSortMissiles(const CViewport *vp,
|
|||
return nmissiles;
|
||||
}
|
||||
|
||||
int FindAndSortMissiles(const CViewport *vp,
|
||||
MissileDrawProxy table[], const int tablesize)
|
||||
int FindAndSortMissiles(const CViewport &vp, MissileDrawProxy table[], const int tablesize)
|
||||
{
|
||||
Assert(tablesize <= MAX_MISSILES * 9);
|
||||
|
||||
Missile *buffer[MAX_MISSILES * 9];
|
||||
int n = FindAndSortMissiles(vp, buffer, MAX_MISSILES * 9);
|
||||
const int n = FindAndSortMissiles(vp, buffer, MAX_MISSILES * 9);
|
||||
|
||||
if (n > 0) {
|
||||
table[0] = buffer[0];
|
||||
for (int i = 1; i < n; ++i) {
|
||||
table[i] = buffer[i];
|
||||
}
|
||||
for (int i = 0; i < n; ++i) {
|
||||
table[i] = buffer[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -764,7 +746,7 @@ static int PointToPointMissile(Missile &missile)
|
|||
|
||||
if (missile.Type->SmokeMissile && missile.CurrentStep) {
|
||||
const PixelPos position = missile.position + missile.Type->size / 2;
|
||||
MakeMissile(missile.Type->SmokeMissile, position, position);
|
||||
MakeMissile(*missile.Type->SmokeMissile, position, position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -794,7 +776,7 @@ static int TracerMissile(Missile &missile)
|
|||
|
||||
if (missile.Type->SmokeMissile && missile.CurrentStep) {
|
||||
const PixelPos position = missile.position + missile.Type->size / 2;
|
||||
MakeMissile(missile.Type->SmokeMissile, position, position);
|
||||
MakeMissile(*missile.Type->SmokeMissile, position, position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -835,7 +817,7 @@ static int ParabolicMissile(Missile &missile)
|
|||
MissileNewHeadingFromXY(missile, missile.position - orig_pos);
|
||||
if (missile.Type->SmokeMissile && missile.CurrentStep) {
|
||||
const PixelPos position = missile.position + missile.Type->size / 2;
|
||||
MakeMissile(missile.Type->SmokeMissile, position, position);
|
||||
MakeMissile(*missile.Type->SmokeMissile, position, position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -913,7 +895,7 @@ static void MissileHit(Missile &missile)
|
|||
// The impact generates a new missile.
|
||||
//
|
||||
if (mtype.ImpactMissile) {
|
||||
MakeMissile(mtype.ImpactMissile, pixelPos, pixelPos);
|
||||
MakeMissile(*mtype.ImpactMissile, pixelPos, pixelPos);
|
||||
}
|
||||
if (mtype.ImpactParticle) {
|
||||
mtype.ImpactParticle->pushPreamble();
|
||||
|
@ -1162,9 +1144,9 @@ void MissileActions()
|
|||
**
|
||||
** @return the computed value.
|
||||
*/
|
||||
int ViewPointDistanceToMissile(const Missile *missile)
|
||||
int ViewPointDistanceToMissile(const Missile &missile)
|
||||
{
|
||||
const PixelPos pixelPos = missile->position + missile->Type->size / 2;
|
||||
const PixelPos pixelPos = missile.position + missile.Type->size / 2;
|
||||
const Vec2i tilePos = { pixelPos.x / PixelTileSize.x, pixelPos.y / PixelTileSize.y };
|
||||
|
||||
return ViewPointDistance(tilePos);
|
||||
|
@ -1188,39 +1170,47 @@ MissileType *MissileBurningBuilding(int percent)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
** Save a specific pos.
|
||||
*/
|
||||
static void SavePixelPos(CFile &file, const PixelPos &pos)
|
||||
{
|
||||
file.printf("{%d, %d}", pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Save the state of a missile to file.
|
||||
**
|
||||
** @param file Output file.
|
||||
*/
|
||||
void Missile::SaveMissile(CFile *file) const
|
||||
void Missile::SaveMissile(CFile &file) const
|
||||
{
|
||||
file->printf("Missile(\"type\", \"%s\",", this->Type->Ident.c_str());
|
||||
file->printf(" \"%s\",", this->Local ? "local" : "global");
|
||||
file->printf(" \"pos\", {%d, %d}, \"origin-pos\", {%d, %d}, \"goal\", {%d, %d},",
|
||||
this->position.x, this->position.y, this->source.x, this->source.y, this->destination.x, this->destination.y);
|
||||
file->printf("\n \"frame\", %d, \"state\", %d, \"anim-wait\", %d, \"wait\", %d, \"delay\", %d,\n ",
|
||||
file.printf("Missile(\"type\", \"%s\",", this->Type->Ident.c_str());
|
||||
file.printf(" \"%s\",", this->Local ? "local" : "global");
|
||||
file.printf(" \"pos\", ");
|
||||
SavePixelPos(file, this->position);
|
||||
file.printf(", \"origin-pos\", ");
|
||||
SavePixelPos(file, this->source);
|
||||
file.printf(", \"goal\", ");
|
||||
SavePixelPos(file, this->destination);
|
||||
file.printf(",\n \"frame\", %d, \"state\", %d, \"anim-wait\", %d, \"wait\", %d, \"delay\", %d,\n ",
|
||||
this->SpriteFrame, this->State, this->AnimWait, this->Wait, this->Delay);
|
||||
|
||||
if (this->SourceUnit) {
|
||||
file->printf(" \"source\", \"%s\",", UnitReference(*this->SourceUnit).c_str());
|
||||
file.printf(" \"source\", \"%s\",", UnitReference(*this->SourceUnit).c_str());
|
||||
}
|
||||
if (this->TargetUnit) {
|
||||
file->printf(" \"target\", \"%s\",", UnitReference(*this->TargetUnit).c_str());
|
||||
file.printf(" \"target\", \"%s\",", UnitReference(*this->TargetUnit).c_str());
|
||||
}
|
||||
|
||||
file->printf(" \"damage\", %d,", this->Damage);
|
||||
|
||||
file->printf(" \"ttl\", %d,", this->TTL);
|
||||
file.printf(" \"damage\", %d,", this->Damage);
|
||||
file.printf(" \"ttl\", %d,", this->TTL);
|
||||
if (this->Hidden) {
|
||||
file->printf(" \"hidden\", ");
|
||||
file.printf(" \"hidden\", ");
|
||||
}
|
||||
|
||||
file->printf(" \"step\", {%d, %d}", this->CurrentStep, this->TotalStep);
|
||||
file.printf(" \"step\", {%d, %d}", this->CurrentStep, this->TotalStep);
|
||||
|
||||
// Slot filled in during init
|
||||
|
||||
file->printf(")\n");
|
||||
file.printf(")\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1228,12 +1218,12 @@ void Missile::SaveMissile(CFile *file) const
|
|||
**
|
||||
** @param file Output file.
|
||||
*/
|
||||
void SaveMissiles(CFile *file)
|
||||
void SaveMissiles(CFile &file)
|
||||
{
|
||||
std::vector<Missile *>::const_iterator i;
|
||||
|
||||
file->printf("\n--- -----------------------------------------\n");
|
||||
file->printf("--- MODULE: missiles\n\n");
|
||||
file.printf("\n--- -----------------------------------------\n");
|
||||
file.printf("--- MODULE: missiles\n\n");
|
||||
|
||||
for (i = GlobalMissiles.begin(); i != GlobalMissiles.end(); ++i) {
|
||||
(*i)->SaveMissile(file);
|
||||
|
@ -1248,9 +1238,7 @@ void SaveMissiles(CFile *file)
|
|||
*/
|
||||
void MissileType::Init()
|
||||
{
|
||||
//
|
||||
// Resolve impact missiles and sounds.
|
||||
//
|
||||
if (!this->FiredSound.Name.empty()) {
|
||||
this->FiredSound.Sound = SoundForName(this->FiredSound.Name);
|
||||
}
|
||||
|
@ -1274,7 +1262,6 @@ void InitMissileTypes()
|
|||
#endif
|
||||
for (std::vector<MissileType*>::iterator i = MissileTypes.begin(); i != MissileTypes.end(); ++i) {
|
||||
(*i)->Init();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,21 +87,14 @@ static const char *MissileClassNames[] = {
|
|||
*/
|
||||
static int CclDefineMissileType(lua_State *l)
|
||||
{
|
||||
const char *value;
|
||||
const char *str;
|
||||
MissileType *mtype;
|
||||
unsigned i;
|
||||
std::string file;
|
||||
|
||||
LuaCheckArgs(l, 2);
|
||||
if (!lua_istable(l, 2)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
|
||||
// Slot identifier
|
||||
|
||||
str = LuaToString(l, 1);
|
||||
mtype = MissileTypeByIdent(str);
|
||||
const char *str = LuaToString(l, 1);
|
||||
MissileType *mtype = MissileTypeByIdent(str);
|
||||
|
||||
if (mtype) {
|
||||
DebugPrint("Redefining missile-type `%s'\n" _C_ str);
|
||||
|
@ -114,11 +107,11 @@ static int CclDefineMissileType(lua_State *l)
|
|||
// Ensure we don't divide by zero.
|
||||
mtype->SplashFactor = 100;
|
||||
|
||||
//
|
||||
// Parse the arguments
|
||||
//
|
||||
std::string file;
|
||||
for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
|
||||
value = LuaToString(l, -2);
|
||||
const char *value = LuaToString(l, -2);
|
||||
|
||||
if (!strcmp(value, "File")) {
|
||||
file = LuaToString(l, -1);
|
||||
} else if (!strcmp(value, "Size")) {
|
||||
|
@ -144,9 +137,10 @@ static int CclDefineMissileType(lua_State *l)
|
|||
} else if (!strcmp(value, "ImpactSound")) {
|
||||
mtype->ImpactSound.Name = LuaToString(l, -1);
|
||||
} else if (!strcmp(value, "Class")) {
|
||||
value = LuaToString(l, -1);
|
||||
for (i = 0; MissileClassNames[i]; ++i) {
|
||||
if (!strcmp(value, MissileClassNames[i])) {
|
||||
const char* className = LuaToString(l, -1);
|
||||
unsigned int i = 0;
|
||||
for (; MissileClassNames[i]; ++i) {
|
||||
if (!strcmp(className, MissileClassNames[i])) {
|
||||
mtype->Class = i;
|
||||
break;
|
||||
}
|
||||
|
@ -246,12 +240,12 @@ static int CclMissile(lua_State *l)
|
|||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "local")) {
|
||||
Assert(type);
|
||||
missile = MakeLocalMissile(type, position, destination);
|
||||
missile = MakeLocalMissile(*type, position, destination);
|
||||
missile->Local = 1;
|
||||
--j;
|
||||
} else if (!strcmp(value, "global")) {
|
||||
Assert(type);
|
||||
missile = MakeMissile(type, position, destination);
|
||||
missile = MakeMissile(*type, position, destination);
|
||||
missile->position = position;
|
||||
missile->source = source;
|
||||
missile->destination = destination;
|
||||
|
@ -325,30 +319,23 @@ static int CclMissile(lua_State *l)
|
|||
*/
|
||||
static int CclDefineBurningBuilding(lua_State *l)
|
||||
{
|
||||
const char *value;
|
||||
BurningBuildingFrame *ptr;
|
||||
int args;
|
||||
int j;
|
||||
int subargs;
|
||||
int k;
|
||||
|
||||
for (std::vector<BurningBuildingFrame *>::iterator i = BurningBuildingFrames.begin();
|
||||
i != BurningBuildingFrames.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
BurningBuildingFrames.clear();
|
||||
|
||||
args = lua_gettop(l);
|
||||
for (j = 0; j < args; ++j) {
|
||||
const int args = lua_gettop(l);
|
||||
for (int j = 0; j < args; ++j) {
|
||||
if (!lua_istable(l, j + 1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
BurningBuildingFrame *ptr = new BurningBuildingFrame;
|
||||
const int subargs = lua_objlen(l, j + 1);
|
||||
|
||||
ptr = new BurningBuildingFrame;
|
||||
subargs = lua_objlen(l, j + 1);
|
||||
for (k = 0; k < subargs; ++k) {
|
||||
for (int k = 0; k < subargs; ++k) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
value = LuaToString(l, -1);
|
||||
const char *value = LuaToString(l, -1);
|
||||
lua_pop(l, 1);
|
||||
++k;
|
||||
|
||||
|
|
|
@ -236,38 +236,28 @@ int AreaAdjustVitals::Cast(CUnit &caster, const SpellType *spell, CUnit *target,
|
|||
*/
|
||||
int AreaBombardment::Cast(CUnit &caster, const SpellType *, CUnit *, int x, int y)
|
||||
{
|
||||
int fields;
|
||||
int shards;
|
||||
int damage;
|
||||
::Missile *mis;
|
||||
int offsetx;
|
||||
int offsety;
|
||||
int dx;
|
||||
int dy;
|
||||
int i;
|
||||
MissileType *missile;
|
||||
int fields = this->Fields;
|
||||
const int shards = this->Shards;
|
||||
const int damage = this->Damage;
|
||||
const PixelDiff offset = { this->StartOffsetX, this->StartOffsetY};
|
||||
const MissileType *missile = this->Missile;
|
||||
|
||||
mis = NULL;
|
||||
|
||||
fields = this->Fields;
|
||||
shards = this->Shards;
|
||||
damage = this->Damage;
|
||||
offsetx = this->StartOffsetX;
|
||||
offsety = this->StartOffsetY;
|
||||
missile = this->Missile;
|
||||
while (fields--) {
|
||||
// FIXME: radius configurable...
|
||||
int dx;
|
||||
int dy;
|
||||
|
||||
// FIXME: radius configurable...
|
||||
do {
|
||||
// find new destination in the map
|
||||
dx = x + SyncRand() % 5 - 2;
|
||||
dy = y + SyncRand() % 5 - 2;
|
||||
} while (!Map.Info.IsPointOnMap(dx, dy));
|
||||
for (i = 0; i < shards; ++i) {
|
||||
mis = MakeMissile(missile,
|
||||
dx * PixelTileSize.x + PixelTileSize.x / 2 + offsetx,
|
||||
dy * PixelTileSize.y + PixelTileSize.y / 2 + offsety,
|
||||
dx * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
dy * PixelTileSize.y + PixelTileSize.y / 2);
|
||||
|
||||
const PixelPos dest = { dx * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
dy * PixelTileSize.y + PixelTileSize.y / 2};
|
||||
const PixelPos start = dest + offset;
|
||||
for (int i = 0; i < shards; ++i) {
|
||||
::Missile *mis = MakeMissile(*missile, start, dest);
|
||||
// FIXME: This is just patched up, it works, but I have no idea why.
|
||||
// FIXME: What is the reasoning behind all this?
|
||||
if (mis->Type->Speed) {
|
||||
|
@ -334,18 +324,15 @@ static void EvaluateMissileLocation(const SpellActionMissileLocation *location,
|
|||
*/
|
||||
int SpawnMissile::Cast(CUnit &caster, const SpellType *, CUnit *target, int x, int y)
|
||||
{
|
||||
::Missile *missile;
|
||||
int sx;
|
||||
int sy;
|
||||
int dx;
|
||||
int dy;
|
||||
PixelPos startPos;
|
||||
PixelPos endPos;
|
||||
|
||||
EvaluateMissileLocation(&this->StartPoint,
|
||||
caster, target, x, y, &sx, &sy);
|
||||
caster, target, x, y, &startPos.x, &startPos.y);
|
||||
EvaluateMissileLocation(&this->EndPoint,
|
||||
caster, target, x, y, &dx, &dy);
|
||||
caster, target, x, y, &endPos.x, &endPos.y);
|
||||
|
||||
missile = MakeMissile(this->Missile, sx, sy, dx, dy);
|
||||
::Missile *missile = MakeMissile(*this->Missile, startPos, endPos);
|
||||
missile->TTL = this->TTL;
|
||||
missile->Delay = this->Delay;
|
||||
missile->Damage = this->Damage;
|
||||
|
|
|
@ -1418,16 +1418,14 @@ static void UISelectStateButtonDown(unsigned)
|
|||
UI.ButtonPanel.Update();
|
||||
|
||||
if (MouseButtons & LeftButton) {
|
||||
const CViewport *vp = UI.MouseViewport;
|
||||
const CViewport &vp = *UI.MouseViewport;
|
||||
const PixelPos screenPixelPos = {CursorX, CursorY};
|
||||
const PixelPos mapPixelPos = vp.ScreenToMapPixelPos(screenPixelPos);
|
||||
|
||||
if (!ClickMissile.empty()) {
|
||||
int mx = vp->MapX * PixelTileSize.x + CursorX - vp->X + vp->OffsetX;
|
||||
int my = vp->MapY * PixelTileSize.y + CursorY - vp->Y + vp->OffsetY;
|
||||
MakeLocalMissile(MissileTypeByIdent(ClickMissile),
|
||||
mx, my, mx, my);
|
||||
MakeLocalMissile(*MissileTypeByIdent(ClickMissile), mapPixelPos, mapPixelPos);
|
||||
}
|
||||
int sx = CursorX - vp->X + PixelTileSize.x * vp->MapX + vp->OffsetX;
|
||||
int sy = CursorY - vp->Y + PixelTileSize.y * vp->MapY + vp->OffsetY;
|
||||
SendCommand(sx, sy);
|
||||
SendCommand(mapPixelPos.x, mapPixelPos.y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1438,10 +1436,13 @@ static void UISelectStateButtonDown(unsigned)
|
|||
if (CursorOn == CursorOnMinimap) {
|
||||
int mx = UI.Minimap.Screen2MapX(CursorX);
|
||||
int my = UI.Minimap.Screen2MapY(CursorY);
|
||||
const Vec2i cursorTilePos = {mx, my};
|
||||
|
||||
if (MouseButtons & LeftButton) {
|
||||
int sx = mx * PixelTileSize.x;
|
||||
int sy = my * PixelTileSize.y;
|
||||
const int sx = cursorTilePos.x * PixelTileSize.x + PixelTileSize.x / 2;
|
||||
const int sy = cursorTilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
|
||||
const PixelPos mapPixelPos = {sx, sy};
|
||||
|
||||
UI.StatusLine.Clear();
|
||||
ClearCosts();
|
||||
CursorState = CursorStatePoint;
|
||||
|
@ -1450,14 +1451,11 @@ static void UISelectStateButtonDown(unsigned)
|
|||
CurrentButtonLevel = 0;
|
||||
UI.ButtonPanel.Update();
|
||||
if (!ClickMissile.empty()) {
|
||||
MakeLocalMissile(MissileTypeByIdent(ClickMissile),
|
||||
sx + PixelTileSize.x / 2, sy + PixelTileSize.y / 2, 0, 0);
|
||||
MakeLocalMissile(*MissileTypeByIdent(ClickMissile), mapPixelPos, mapPixelPos);
|
||||
}
|
||||
SendCommand(sx, sy);
|
||||
SendCommand(mapPixelPos.x, mapPixelPos.y);
|
||||
} else {
|
||||
const Vec2i cursorPos = {mx, my};
|
||||
|
||||
UI.SelectedViewport->Center(cursorPos, PixelTileSize / 2);
|
||||
UI.SelectedViewport->Center(cursorTilePos, PixelTileSize / 2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1643,11 +1641,10 @@ void UIHandleButtonDown(unsigned button)
|
|||
unit->Blink = 4; // if right click on building -- blink
|
||||
} else { // if not not click on building -- green cross
|
||||
if (!ClickMissile.empty()) {
|
||||
MakeLocalMissile(MissileTypeByIdent(ClickMissile),
|
||||
UI.MouseViewport->MapX * PixelTileSize.x +
|
||||
CursorX - UI.MouseViewport->X + UI.MouseViewport->OffsetX,
|
||||
UI.MouseViewport->MapY * PixelTileSize.y +
|
||||
CursorY - UI.MouseViewport->Y + UI.MouseViewport->OffsetY, 0, 0);
|
||||
const PixelPos screenPos = {CursorX, CursorY};
|
||||
const PixelPos mapPixelPos = UI.MouseViewport->ScreenToMapPixelPos(screenPos);
|
||||
|
||||
MakeLocalMissile(*MissileTypeByIdent(ClickMissile), mapPixelPos, mapPixelPos);
|
||||
}
|
||||
}
|
||||
DoRightButton(tilePos.x * PixelTileSize.x, tilePos.y * PixelTileSize.y);
|
||||
|
@ -1670,20 +1667,18 @@ void UIHandleButtonDown(unsigned button)
|
|||
// Cursor is on the minimap area
|
||||
//
|
||||
} else if (CursorOn == CursorOnMinimap) {
|
||||
if (MouseButtons & LeftButton) { // enter move mini-mode
|
||||
const Vec2i cursorPos = {UI.Minimap.Screen2MapX(CursorX), UI.Minimap.Screen2MapY(CursorY)};
|
||||
const Vec2i cursorTilePos = {UI.Minimap.Screen2MapX(CursorX), UI.Minimap.Screen2MapY(CursorY)};
|
||||
|
||||
UI.SelectedViewport->Center(cursorPos, PixelTileSize / 2);
|
||||
if (MouseButtons & LeftButton) { // enter move mini-mode
|
||||
UI.SelectedViewport->Center(cursorTilePos, PixelTileSize / 2);
|
||||
} else if (MouseButtons & RightButton) {
|
||||
if (!GameObserve && !GamePaused) {
|
||||
PixelPos mapPixelPos = { cursorTilePos.x * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
cursorTilePos.y * PixelTileSize.y + PixelTileSize.y / 2};
|
||||
if (!ClickMissile.empty()) {
|
||||
MakeLocalMissile(MissileTypeByIdent(ClickMissile),
|
||||
UI.Minimap.Screen2MapX(CursorX) * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
UI.Minimap.Screen2MapY(CursorY) * PixelTileSize.y + PixelTileSize.y / 2, 0, 0);
|
||||
MakeLocalMissile(*MissileTypeByIdent(ClickMissile), mapPixelPos, mapPixelPos);
|
||||
}
|
||||
// DoRightButton() takes screen map coordinates
|
||||
DoRightButton(UI.Minimap.Screen2MapX(CursorX) * PixelTileSize.x,
|
||||
UI.Minimap.Screen2MapY(CursorY) * PixelTileSize.y);
|
||||
DoRightButton(mapPixelPos.x, mapPixelPos.y);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
|
|
@ -541,7 +541,7 @@ static void MapMarkUnitSightRec(const CUnit &unit, const Vec2i &pos, int width,
|
|||
**
|
||||
** @return Container of container of ... of unit. It is not null.
|
||||
*/
|
||||
static CUnit *GetFirstContainer(const CUnit &unit)
|
||||
CUnit *GetFirstContainer(const CUnit &unit)
|
||||
{
|
||||
const CUnit *container = &unit;
|
||||
|
||||
|
@ -2763,6 +2763,13 @@ CUnit *UnitOnScreen(CUnit *ounit, int x, int y)
|
|||
return nunit;
|
||||
}
|
||||
|
||||
PixelPos CUnit::GetMapPixelPosCenter() const
|
||||
{
|
||||
const PixelPos center = { tilePos.x * PixelTileSize.x + Type->TileWidth * PixelTileSize.x / 2,
|
||||
tilePos.y * PixelTileSize.y + Type->TileHeight * PixelTileSize.y / 2};
|
||||
return center;
|
||||
}
|
||||
|
||||
/**
|
||||
** Let an unit die.
|
||||
**
|
||||
|
@ -2795,17 +2802,16 @@ void LetUnitDie(CUnit &unit)
|
|||
// Catapults,... explodes.
|
||||
//
|
||||
if (type->ExplodeWhenKilled) {
|
||||
MakeMissile(type->Explosion.Missile,
|
||||
unit.tilePos.x * PixelTileSize.x + type->TileWidth * PixelTileSize.x / 2,
|
||||
unit.tilePos.y * PixelTileSize.y + type->TileHeight * PixelTileSize.y / 2,
|
||||
0, 0);
|
||||
const PixelPos pixelPos = unit.GetMapPixelPosCenter();
|
||||
|
||||
MakeMissile(*type->Explosion.Missile, pixelPos, pixelPos);
|
||||
}
|
||||
if (type->DeathExplosion) {
|
||||
const PixelPos pixelPos = unit.GetMapPixelPosCenter();
|
||||
|
||||
type->DeathExplosion->pushPreamble();
|
||||
type->DeathExplosion->pushInteger(unit.tilePos.x * PixelTileSize.x +
|
||||
type->TileWidth * PixelTileSize.x / 2);
|
||||
type->DeathExplosion->pushInteger(unit.tilePos.y * PixelTileSize.y +
|
||||
type->TileHeight * PixelTileSize.y / 2);
|
||||
type->DeathExplosion->pushInteger(pixelPos.x);
|
||||
type->DeathExplosion->pushInteger(pixelPos.y);
|
||||
type->DeathExplosion->run();
|
||||
}
|
||||
// Handle Teleporter Destination Removal
|
||||
|
@ -3031,29 +3037,23 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
|
|||
CommandStopUnit(*attacker); // Attacker shouldn't continue attack!
|
||||
}
|
||||
|
||||
const PixelPos targetPixelCenter = target.GetMapPixelPosCenter();
|
||||
|
||||
if ((target.IsVisibleOnMap(*ThisPlayer) || ReplayRevealMap) && !DamageMissile.empty()) {
|
||||
MakeLocalMissile(MissileTypeByIdent(DamageMissile),
|
||||
target.tilePos.x * PixelTileSize.x + target.Type->TileWidth * PixelTileSize.x / 2,
|
||||
target.tilePos.y * PixelTileSize.y + target.Type->TileHeight * PixelTileSize.y / 2,
|
||||
target.tilePos.x * PixelTileSize.x + target.Type->TileWidth * PixelTileSize.x / 2 + 3,
|
||||
target.tilePos.y * PixelTileSize.y + target.Type->TileHeight * PixelTileSize.y / 2 -
|
||||
MissileTypeByIdent(DamageMissile)->Range)->Damage = -damage;
|
||||
MissileType *mtype = MissileTypeByIdent(DamageMissile);
|
||||
const PixelDiff offset = {3, -mtype->Range};
|
||||
|
||||
MakeLocalMissile(*mtype, targetPixelCenter, targetPixelCenter + offset)->Damage = -damage;
|
||||
}
|
||||
|
||||
// Show impact missiles
|
||||
if (target.Variable[SHIELD_INDEX].Value > 0
|
||||
&& !target.Type->Impact[ANIMATIONS_DEATHTYPES+1].Name.empty()) { // shield impact
|
||||
MakeMissile(target.Type->Impact[ANIMATIONS_DEATHTYPES+1].Missile,
|
||||
target.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
target.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2, 0, 0);
|
||||
&& !target.Type->Impact[ANIMATIONS_DEATHTYPES + 1].Name.empty()) { // shield impact
|
||||
MakeMissile(*target.Type->Impact[ANIMATIONS_DEATHTYPES + 1].Missile, targetPixelCenter, targetPixelCenter);
|
||||
} else if (target.DamagedType && !target.Type->Impact[target.DamagedType].Name.empty()) { // specific to damage type impact
|
||||
MakeMissile(target.Type->Impact[target.DamagedType].Missile,
|
||||
target.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
target.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2, 0, 0);
|
||||
MakeMissile(*target.Type->Impact[target.DamagedType].Missile, targetPixelCenter, targetPixelCenter);
|
||||
} else if (!target.Type->Impact[ANIMATIONS_DEATHTYPES].Name.empty()) { // generic impact
|
||||
MakeMissile(target.Type->Impact[ANIMATIONS_DEATHTYPES].Missile,
|
||||
target.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2,
|
||||
target.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2, 0, 0);
|
||||
MakeMissile(*target.Type->Impact[ANIMATIONS_DEATHTYPES].Missile, targetPixelCenter, targetPixelCenter);
|
||||
}
|
||||
|
||||
if (type->Building && !target.Burning) {
|
||||
|
@ -3061,13 +3061,12 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
|
|||
MissileType *fire = MissileBurningBuilding(f);
|
||||
|
||||
if (fire) {
|
||||
Missile *missile = MakeMissile(fire,
|
||||
target.tilePos.x * PixelTileSize.x + (type->TileWidth * PixelTileSize.x) / 2,
|
||||
target.tilePos.y * PixelTileSize.y + (type->TileHeight * PixelTileSize.y) / 2 - PixelTileSize.y,
|
||||
0, 0);
|
||||
const PixelDiff offset = {0, -PixelTileSize.y};
|
||||
Missile *missile = MakeMissile(*fire, targetPixelCenter - offset, targetPixelCenter - offset);
|
||||
|
||||
target.RefsIncrease();
|
||||
missile->SourceUnit = ⌖
|
||||
target.Burning = 1;
|
||||
target.RefsIncrease();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue