[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stratagus-CVS] stratagus data/ccl/missiles.ccl data/ccl/spells...
From: |
Crestez Leonard |
Subject: |
[Stratagus-CVS] stratagus data/ccl/missiles.ccl data/ccl/spells... |
Date: |
Mon, 13 Oct 2003 07:21:11 -0400 |
CVSROOT: /cvsroot/stratagus
Module name: stratagus
Branch:
Changes by: Crestez Leonard <address@hidden> 03/10/13 07:21:09
Modified files:
data/ccl : missiles.ccl spells.ccl stratagus.ccl
src/clone : ccl_spell.c spells.c
src/include : missile.h spells.h
src/missile : missile.c
Log message:
Missiles mostly work, but need a big cleanup.
Patches:
Index: stratagus/data/ccl/missiles.ccl
diff -u stratagus/data/ccl/missiles.ccl:1.34
stratagus/data/ccl/missiles.ccl:1.35
--- stratagus/data/ccl/missiles.ccl:1.34 Sun Oct 5 22:56:06 2003
+++ stratagus/data/ccl/missiles.ccl Mon Oct 13 07:21:05 2003
@@ -26,7 +26,7 @@
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
;;
-;; $Id: missiles.ccl,v 1.34 2003/10/06 02:56:06 jsalmon3 Exp $
+;; $Id: missiles.ccl,v 1.35 2003/10/13 11:21:05 n0body Exp $
;; NOTE: the missiles could be sorted for races, but did this make sense?
@@ -58,7 +58,8 @@
(define-missile-type 'missile-fireball
'file "missiles/fireball.png" 'size '(32 32) 'frames 5
'impact-sound "fireball hit"
- 'draw-level 50 'class 'missile-class-point-to-point 'sleep 1 'speed 16
'range 1)
+ 'draw-level 50 'class 'missile-class-point-to-point 'sleep 1 'speed 16
'range 1
+ 'impact-missile 'missile-explosion)
(define-missile-type 'missile-flame-shield
'file "missiles/flame_shield.png" 'size '(32 48) 'frames 6
@@ -93,7 +94,8 @@
(define-missile-type 'missile-rune
'file "missiles/rune.png" 'size '(16 16) 'frames 4
- 'draw-level 20 'class 'missile-class-stay-with-delay 'sleep 5 'speed 16
'range 1)
+ 'draw-level 20 'class 'missile-class-land-mine 'sleep 5 'speed 16 'range 1
+ 'impact-missile 'missile-explosion)
(define-missile-type 'missile-whirlwind
'file "missiles/tornado.png" 'size '(56 56) 'frames 4
Index: stratagus/data/ccl/spells.ccl
diff -u stratagus/data/ccl/spells.ccl:1.8 stratagus/data/ccl/spells.ccl:1.9
--- stratagus/data/ccl/spells.ccl:1.8 Thu Oct 9 07:31:41 2003
+++ stratagus/data/ccl/spells.ccl Mon Oct 13 07:21:06 2003
@@ -26,7 +26,7 @@
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
;;
-;; $Id: spells.ccl,v 1.8 2003/10/09 11:31:41 n0body Exp $
+;; $Id: spells.ccl,v 1.9 2003/10/13 11:21:06 n0body Exp $
;; For documentation see stratagus/doc/ccl/ccl.html ;; FIXME write and move
doc.
@@ -228,7 +228,7 @@
'manacost 50
'range 6
'target 'unit
- 'action '(flame-shield duration 600)
+ 'action '(flame-shield duration 600 damage 1)
;; I think it's better if we can cast it multiple times and the effects
stack.
;; Can be casted, and is effective on both allies and enemies
'condition '(building false)
Index: stratagus/data/ccl/stratagus.ccl
diff -u stratagus/data/ccl/stratagus.ccl:1.19
stratagus/data/ccl/stratagus.ccl:1.20
--- stratagus/data/ccl/stratagus.ccl:1.19 Tue Oct 7 12:27:17 2003
+++ stratagus/data/ccl/stratagus.ccl Mon Oct 13 07:21:06 2003
@@ -26,7 +26,7 @@
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
;;
-;; $Id: stratagus.ccl,v 1.19 2003/10/07 16:27:17 jsalmon3 Exp $
+;; $Id: stratagus.ccl,v 1.20 2003/10/13 11:21:06 n0body Exp $
;; For documentation see stratagus/doc/ccl/ccl.html
@@ -56,7 +56,7 @@
;; Enter your default title screen.
(set-title-screen! "graphics/ui/stratagus.png")
-;(set-title-screen! "videos/splash2.avi")
+;(set-title-screen! "graphics/logo_stratagus.avi")
;; Enter your title music.
(set-title-music! "music/default.mod")
Index: stratagus/src/clone/ccl_spell.c
diff -u stratagus/src/clone/ccl_spell.c:1.15
stratagus/src/clone/ccl_spell.c:1.16
--- stratagus/src/clone/ccl_spell.c:1.15 Thu Oct 9 16:54:36 2003
+++ stratagus/src/clone/ccl_spell.c Mon Oct 13 07:21:06 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: ccl_spell.c,v 1.15 2003/10/09 20:54:36 jsalmon3 Exp $
+// $Id: ccl_spell.c,v 1.16 2003/10/13 11:21:06 n0body Exp $
//@{
/*----------------------------------------------------------------------------
@@ -100,7 +100,10 @@
spellaction->Data.FlameShield.TTL = gh_scm2int(gh_car(list));
list = gh_cdr(list);
/// FIXME:damage, missiles, rotation speed?
- } else {
+ } else if (gh_eq_p(value, gh_symbol2scm("damage"))) {
+ spellaction->Data.FlameShield.Damage = gh_scm2int(gh_car(list));
+ list = gh_cdr(list);
+ }else {
errl("Unsupported flame-shield tag", value);
}
}
@@ -125,10 +128,10 @@
value = gh_car(list);
list = gh_cdr(list);
if (gh_eq_p(value, gh_symbol2scm("damage"))) {
- spellaction->Data.Fireball.Damage = gh_scm2int(gh_car(list));
+ spellaction->Data.Runes.Damage = gh_scm2int(gh_car(list));
list = gh_cdr(list);
} else if (gh_eq_p(value, gh_symbol2scm("ttl"))) {
- spellaction->Data.Fireball.TTL = gh_scm2int(gh_car(list));
+ spellaction->Data.Runes.TTL = gh_scm2int(gh_car(list));
list = gh_cdr(list);
} else {
errl("Unsupported runes tag", value);
Index: stratagus/src/clone/spells.c
diff -u stratagus/src/clone/spells.c:1.108 stratagus/src/clone/spells.c:1.109
--- stratagus/src/clone/spells.c:1.108 Thu Oct 9 23:56:40 2003
+++ stratagus/src/clone/spells.c Mon Oct 13 07:21:07 2003
@@ -27,7 +27,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.c,v 1.108 2003/10/10 03:56:40 jsalmon3 Exp $
+// $Id: spells.c,v 1.109 2003/10/13 11:21:07 n0body Exp $
/*
** And when we cast our final spell
@@ -65,9 +65,6 @@
-- Definitons
----------------------------------------------------------------------------*/
-// TODO Move this in missile.c and remove Hardcoded string.
-MissileType* MissileTypeRune; // MissileTypeByIdent("missile-rune");
-
/*----------------------------------------------------------------------------
-- Variables
----------------------------------------------------------------------------*/
@@ -82,349 +79,6 @@
global int SpellTypeCount;
/*----------------------------------------------------------------------------
--- Functions (Spells Controllers/Callbacks)
-----------------------------------------------------------------------------*/
-
-// ****************************************************************************
-// Action of the missile of spells
-// ****************************************************************************
-
-/*
-** Missile controllers
-**
-** To cancel a missile set it's TTL to 0, it will be handled right after
-** the controller call and missile will be down.
-**
-*/
-
-// FIXME Move this codes into missile.c
-
-/**
-** Fireball controller
-**
-** @param missile Controlled missile
-**
-** @todo Move this code into the missile code
-*/
-local void SpellFireballController(Missile* missile)
-{
- Unit* table[UnitMax];
- int i;
- int n;
- int x;
- int y;
-
- //NOTE: vladi: TTL is used as counter for explosions
- // explosions start at target and continue (10 tiles) beyond
- // explosions are on each tile on the way
-
- // approx
- if (missile->TTL <= missile->State && missile->TTL % 2 == 0) {
- //+TileSize/2 to align gfx to baseline
- x = missile->X + TileSizeX / 2;
- y = missile->Y + TileSizeY / 2;
-
- MakeMissile(MissileTypeExplosion, x, y, x, y);
-
- x = x / TileSizeX;
- y = y / TileSizeY;
-
- // Effect of the explosion on units
- // NOTE: vladi: this is slightly different than original
- // now it hits all units in range 1
- n = SelectUnits(x - 1, y - 1, x + 1, y + 1, table);
- for (i = 0; i < n; ++i) {
- if (table[i]->HP) {
- HitUnit(missile->SourceUnit, table[i], FIREBALL_DAMAGE); //
Should be missile->damage
- }
- }
- }
-}
-
-/**
-** Death-Coil controller
-**
-** @param missile Controlled missile
-**
-** @todo Move this code into the missile code
-*/
-local void SpellDeathCoilController(Missile* missile)
-{
- Unit* table[UnitMax];
- int i;
- int n;
- Unit* source;
-
- //
- // missile has not reached target unit/spot
- //
- if (!(missile->X == missile->DX && missile->Y == missile->DY)) {
- return;
- }
- source = missile->SourceUnit;
- if (source->Destroyed) {
- return;
- }
- // source unit still exists
- //
- // Target unit still exists and casted on a special target
- //
- if (missile->TargetUnit && !missile->TargetUnit->Destroyed &&
- missile->TargetUnit->HP) {
- if (missile->TargetUnit->HP <= 50) {// 50 should be parametrable
- source->Player->Score += missile->TargetUnit->Type->Points;
- if (missile->TargetUnit->Type->Building) {
- source->Player->TotalRazings++;
- } else {
- source->Player->TotalKills++;
- }
-#ifdef USE_HP_FOR_XP
- source->XP += missile->TargetUnit->HP;
-#else
- source->XP += missile->TargetUnit->Type->Points;
-#endif
- ++source->Kills;
- missile->TargetUnit->HP = 0;
- LetUnitDie(missile->TargetUnit);
- } else {
-#ifdef USE_HP_FOR_XP
- source->XP += 50;
-#endif
- missile->TargetUnit->HP -= 50;
- }
- if (source->Orders[0].Action != UnitActionDie) {
- source->HP += 50;
- if (source->HP > source->Stats->HitPoints) {
- source->HP = source->Stats->HitPoints;
- }
- }
- } else {
- //
- // No target unit -- try enemies in range 5x5 // Must be parametrable
- //
- int ec; // enemy count
- int x;
- int y;
-
- ec = 0;
- x = missile->DX / TileSizeX;
- y = missile->DY / TileSizeY;
-
- n = SelectUnits(x - 2, y - 2, x + 2, y + 2, table);
- if (n == 0) {
- return;
- }
- // calculate organic enemy count
- for (i = 0; i < n; ++i) {
- ec += (IsEnemy(source->Player, table[i]) && table[i]->Type->Organic
!= 0);
- }
- if (ec > 0) {
- // yes organic enemies found
- for (i = 0; i < n; ++i) {
- if (IsEnemy(source->Player, table[i]) &&
table[i]->Type->Organic != 0) {
- // disperse damage between them
- //NOTE: 1 is the minimal damage
- if (table[i]->HP <= 50 / ec) {
- source->Player->Score += table[i]->Type->Points;
- if (table[i]->Type->Building) {
- source->Player->TotalRazings++;
- } else {
- source->Player->TotalKills++;
- }
-#ifdef USE_HP_FOR_XP
- source->XP += table[i]->HP;
-#else
- source->XP += table[i]->Type->Points;
-#endif
- ++source->Kills;
- table[i]->HP = 0;
- LetUnitDie(table[i]); // too much damage
- } else {
-#ifdef USE_HP_FOR_XP
- source->XP += 50 / ec;
-#endif
- table[i]->HP -= 50 / ec;
- }
- }
- }
- if (source->Orders[0].Action != UnitActionDie) {
- source->HP += 50;
- if (source->HP > source->Stats->HitPoints) {
- source->HP = source->Stats->HitPoints;
- }
- }
- }
- }
-}
-
-/**
-** Whirlwind controller
-**
-** @param missile Controlled missile
-**
-** @todo Move this code into the missile code
-*/
-local void SpellWhirlwindController(Missile* missile)
-{
- Unit* table[UnitMax];
- int i;
- int n;
- int x;
- int y;
-
- //
- // Center of the tornado
- //
- x = (missile->X + TileSizeX / 2 + missile->Type->Width / 2) / TileSizeX;
- y = (missile->Y + TileSizeY + missile->Type->Height / 2) / TileSizeY;
- //
- // Every 4 cycles 4 points damage in tornado center
- //
- if (!(missile->TTL % 4)) {
- n = SelectUnitsOnTile(x, y, table);
- for (i = 0; i < n; ++i) {
- if (table[i]->HP) {
- // should be missile damage?
- HitUnit(missile->SourceUnit, table[i], WHIRLWIND_DAMAGE1);
- }
- }
- }
- //
- // Every 1/10s 1 points damage on tornado periphery
- //
- if (!(missile->TTL % (CYCLES_PER_SECOND / 10))) {
- // we should parameter this
- n = SelectUnits(x - 1, y - 1, x + 1, y + 1, table);
- DebugLevel3Fn("Damage on %d,%d-%d,%d = %d\n" _C_ x-1 _C_ y-1 _C_ x+1
_C_ y+1 _C_ n);
- for (i = 0; i < n; ++i) {
- if ((table[i]->X != x || table[i]->Y != y) && table[i]->HP) {
- // should be in missile
- HitUnit(missile->SourceUnit, table[i], WHIRLWIND_DAMAGE2);
- }
- }
- }
- DebugLevel3Fn("Whirlwind: %d, %d, TTL: %d\n" _C_
- missile->X _C_ missile->Y _C_ missile->TTL);
-
- //
- // Changes direction every 3 seconds (approx.)
- //
- if (!(missile->TTL % 100)) { // missile has reached target unit/spot
- int nx;
- int ny;
-
- do {
- // find new destination in the map
- nx = x + SyncRand() % 5 - 2;
- ny = y + SyncRand() % 5 - 2;
- } while (nx < 0 && ny < 0 && nx >= TheMap.Width && ny >= TheMap.Height);
- missile->DX = nx * TileSizeX + TileSizeX / 2;
- missile->DY = ny * TileSizeY + TileSizeY / 2;
- missile->State = 0;
- DebugLevel3Fn("Whirlwind new direction: %d, %d, TTL: %d\n" _C_
- missile->X _C_ missile->Y _C_ missile->TTL);
- }
-}
-
-/**
-** Runes controller
-**
-** @param missile Controlled missile
-**
-** @todo Move this code into the missile code
-*/
-local void SpellRunesController(Missile* missile)
-{
- Unit* table[UnitMax];
- int i;
- int n;
- int x;
- int y;
-
- x = missile->X / TileSizeX;
- y = missile->Y / TileSizeY;
-
- n = SelectUnitsOnTile(x, y, table);
- for (i = 0; i < n; ++i) {
- if (table[i]->Type->UnitType != UnitTypeFly && table[i]->HP) {
- // FIXME: don't use ident!!!
- PlayMissileSound(missile, SoundIdForName("explosion"));
- MakeMissile(MissileTypeExplosion, missile->X, missile->Y,
- missile->X, missile->Y);
- HitUnit(missile->SourceUnit, table[i], RUNE_DAMAGE);
- missile->TTL = 0; // Rune can only hit once
- }
- }
- // show rune every 4 seconds (approx.)
- if (missile->TTL % 100 == 0) {
- MakeMissile(MissileTypeRune, missile->X, missile->Y, missile->X,
missile->Y);
- }
-}
-
-/**
-** FlameShield controller
-**
-** @param missile Controlled missile
-**
-** @todo Move this code into the missile code
-*/
-local void SpellFlameShieldController(Missile* missile)
-{
- static int fs_dc[] = {
- 0, 32, 5, 31, 10, 30, 16, 27, 20, 24, 24, 20, 27, 15, 30, 10, 31,
- 5, 32, 0, 31, -5, 30, -10, 27, -16, 24, -20, 20, -24, 15, -27, 10,
- -30, 5, -31, 0, -32, -5, -31, -10, -30, -16, -27, -20, -24, -24, -20,
- -27, -15, -30, -10, -31, -5, -32, 0, -31, 5, -30, 10, -27, 16, -24,
- 20, -20, 24, -15, 27, -10, 30, -5, 31, 0, 32};
- Unit* table[UnitMax];
- int n;
- int i;
- int dx;
- int dy;
- int ux;
- int uy;
- int ix;
- int iy;
- int uw;
- int uh;
-
- i = missile->TTL % 36; // 36 positions on the circle
- dx = fs_dc[i * 2];
- dy = fs_dc[i * 2 + 1];
- ux = missile->TargetUnit->X;
- uy = missile->TargetUnit->Y;
- ix = missile->TargetUnit->IX;
- iy = missile->TargetUnit->IY;
- uw = missile->TargetUnit->Type->Width;
- uh = missile->TargetUnit->Type->Height;
- missile->X = ux * TileSizeX + ix + uw / 2 + dx - 32;
- missile->Y = uy * TileSizeY + iy + uh / 2 + dy - 32 - 16;
- if (missile->TargetUnit->Orders[0].Action == UnitActionDie) {
- missile->TTL = i;
- }
- if (missile->TTL == 0) {
- missile->TargetUnit->FlameShield = 0;
- }
- //vladi: still no have clear idea what is this about :)
- CheckMissileToBeDrawn(missile);
-
- // Only hit 1 out of 8 frames
- if (missile->TTL & 7) {
- return;
- }
- n = SelectUnits(ux - 1, uy - 1, ux + 1 + 1, uy + 1 + 1, table);
- for (i = 0; i < n; ++i) {
- if (table[i] == missile->TargetUnit) {
- // cannot hit target unit
- continue;
- }
- if (table[i]->HP) {
- HitUnit(missile->SourceUnit, table[i], 1);
- }
- }
-}
-
-/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
@@ -637,6 +291,7 @@
missile = MakeMissile(spell->Missile, sx, sy, x, y);
missile->State = spell->Action->Data.Fireball.TTL - (dist - 1) * 2;
missile->TTL = spell->Action->Data.Fireball.TTL;
+ missile->Damage = spell->Action->Data.Fireball.Damage;
missile->Controller = SpellFireballController;
missile->SourceUnit = caster;
RefsDebugCheck(!caster->Refs || caster->Destroyed);
@@ -679,6 +334,7 @@
mis->TTL = spell->Action->Data.FlameShield.TTL + i * 7;
mis->TargetUnit = target;
mis->Controller = SpellFlameShieldController;
+ mis->Damage = spell->Action->Data.FlameShield.Damage;
RefsDebugCheck(!target->Refs || target->Destroyed);
target->Refs++;
}
@@ -896,7 +552,7 @@
int i;
DebugCheck(!caster);
- DebugCheck(spell);
+ DebugCheck(!spell);
DebugCheck(!spell->Action);
// DebugCheck(x in range, y in range);
@@ -909,14 +565,15 @@
x = oldx + xx[i];
y = oldy + yy[i];
- if (IsMapFieldEmpty(x - 1, y + 0)) {
+ if (IsMapFieldEmpty(x, y)) {
mis = MakeMissile(spell->Missile,
x * TileSizeX + TileSizeX / 2,
y * TileSizeY + TileSizeY / 2,
x * TileSizeX + TileSizeX / 2,
y * TileSizeY + TileSizeY / 2);
mis->TTL = spell->Action->Data.Runes.TTL;
- mis->Controller = SpellRunesController;
+ mis->Damage = spell->Action->Data.Runes.Damage;
+ mis->SourceUnit = caster;
caster->Mana -= spell->ManaCost / 5;
}
}
Index: stratagus/src/include/missile.h
diff -u stratagus/src/include/missile.h:1.67
stratagus/src/include/missile.h:1.68
--- stratagus/src/include/missile.h:1.67 Thu Oct 9 07:31:46 2003
+++ stratagus/src/include/missile.h Mon Oct 13 07:21:08 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: missile.h,v 1.67 2003/10/09 11:31:46 n0body Exp $
+// $Id: missile.h,v 1.68 2003/10/13 11:21:08 n0body Exp $
#ifndef __MISSILE_H__
#define __MISSILE_H__
@@ -404,9 +404,13 @@
*/
MissileClassHit,
/**
- ** Missile flies from x,y to x1,y1 using a parabolic path
+ ** Missile flies from x,y to x1,y1 using a parabolic path
*/
MissileClassParabolic,
+ /**
+ ** Missile wait on x,1 until a non-air unit comes by, the explodes.
+ */
+ MissileClassLandMine,
};
/// Base structure of missile-types
@@ -450,6 +454,7 @@
** Missile typedef.
*/
typedef struct _missile_ Missile;
+typedef void FuncController(Missile *);
/// Missile on the map
struct _missile_ {
@@ -469,7 +474,7 @@
int Damage; /// direct damage that missile
applies
int TTL; /// time to live (ticks) used
for spells
- void (*Controller)( Missile* ); /// used to controll spells
+ FuncController *Controller; /// used to controll spells
// Internal use:
int D; /// for point to point missiles
@@ -500,7 +505,6 @@
extern char** MissileTypeWcNames; /// Mapping wc-number 2 symbol
extern MissileType* MissileTypes; /// All missile-types
-extern MissileType* MissileTypeExplosion; /// Explosion missile-type
extern const char* MissileClassNames[]; /// Missile class names
@@ -557,6 +561,24 @@
extern void InitMissiles(void);
/// Clean missiles
extern void CleanMissiles(void);
+
+FuncController SpellDeathCoilController;
+FuncController SpellFireballController;
+FuncController SpellFlameShieldController;
+FuncController SpellRunesController;
+FuncController SpellWhirlwindController;
+
+FuncController MissileActionNone;
+FuncController MissileActionPointToPoint;
+FuncController MissileActionPointToPointWithDelay;
+FuncController MissileActionStayWithDelay;
+FuncController MissileActionPointToPoint3Bounces;
+FuncController MissileActionCycleOnce;
+FuncController MissileActionPointToPointWithHit;
+FuncController MissileActionFire;
+FuncController MissileActionHit;
+FuncController MissileActionParabolic;
+FuncController MissileActionLandMine;
//@}
Index: stratagus/src/include/spells.h
diff -u stratagus/src/include/spells.h:1.30 stratagus/src/include/spells.h:1.31
--- stratagus/src/include/spells.h:1.30 Thu Oct 9 07:31:46 2003
+++ stratagus/src/include/spells.h Mon Oct 13 07:21:08 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.h,v 1.30 2003/10/09 11:31:46 n0body Exp $
+// $Id: spells.h,v 1.31 2003/10/13 11:21:08 n0body Exp $
#ifndef __SPELLS_H__
#define __SPELLS_H__
@@ -51,12 +51,6 @@
-- Definitons
----------------------------------------------------------------------------*/
-// TODO : Remove, configure in ccl.
-#define FIREBALL_DAMAGE 20 /// Damage of center fireball
-#define WHIRLWIND_DAMAGE1 4 /// the center of the whirlwind
-#define WHIRLWIND_DAMAGE2 1 /// the periphery of the whirlwind
-#define RUNE_DAMAGE 50 /// Rune damage
-
enum {
flag_slow,
flag_haste,
@@ -118,6 +112,7 @@
struct {
int TTL; /// time to live (ticks)
+ int Damage; /// Damage.
} FlameShield;
struct {
Index: stratagus/src/missile/missile.c
diff -u stratagus/src/missile/missile.c:1.90
stratagus/src/missile/missile.c:1.91
--- stratagus/src/missile/missile.c:1.90 Sun Oct 12 12:18:12 2003
+++ stratagus/src/missile/missile.c Mon Oct 13 07:21:08 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: missile.c,v 1.90 2003/10/12 16:18:12 n0body Exp $
+// $Id: missile.c,v 1.91 2003/10/13 11:21:08 n0body Exp $
//@{
@@ -59,6 +59,13 @@
-- Declarations
----------------------------------------------------------------------------*/
+// TODO : Remove, configure in ccl.
+// #define FIREBALL_DAMAGE 20 /// Damage of center fireball
+#define WHIRLWIND_DAMAGE1 4 /// the center of the whirlwind
+#define WHIRLWIND_DAMAGE2 1 /// the periphery of the whirlwind
+//#define RUNE_DAMAGE 50 /// Rune damage
+
+
/**
** Missile class names, used to load/save the missiles.
*/
@@ -79,6 +86,7 @@
"missile-class-custom",
"missile-class-hit",
"missile-class-parabolic",
+ "missile-class-land-mine",
NULL
};
@@ -99,12 +107,6 @@
global int NumMissileTypes; /// number of missile-types made.
-/*
-** Next missile-types are used hardcoded in the source.
-*/
- /// missile-type for the explosion missile
-global MissileType* MissileTypeExplosion;
-
#ifdef DEBUG
global int NoWarningMissileType; /// quiet ident lookup.
#endif
@@ -170,6 +172,7 @@
{
MissileType* const* mtype;
+ DebugCheck(ident == NULL);
mtype = (MissileType**)hash_find(MissileTypeHash, (char*)ident);
if (mtype) {
return *mtype;
@@ -198,6 +201,7 @@
MissileType* mtype;
int i;
+ DebugCheck(ident == NULL);
//
// Allocate new memory. (+2 for start end empty last entry.)
//
@@ -242,6 +246,7 @@
}
missile = calloc(1, sizeof(Missile));
+ memset(missile, 0, sizeof (*missile));
missile->MissileSlot = GlobalMissiles + NumGlobalMissiles;
GlobalMissiles[NumGlobalMissiles++] = missile;
@@ -263,6 +268,7 @@
}
missile = calloc(1, sizeof(Missile));
+ memset(missile, 0, sizeof (*missile));
missile->MissileSlot = LocalMissiles + NumLocalMissiles;
LocalMissiles[NumLocalMissiles++] = missile;
missile->Local = 1;
@@ -271,7 +277,7 @@
}
/**
-** Initialize a new made missle.
+** Initialize a new made missile.
**
** @param missile Pointer to new uninitialized missile.
** @param mtype Type pointer of missile.
@@ -372,6 +378,7 @@
Missile* temp;
Unit* unit;
+ DebugCheck(missile == NULL);
//
// Release all unit references.
//
@@ -494,6 +501,8 @@
local int CalculateDamage(const UnitStats* attacker_stats,
const Unit* goal, int bloodlust, int xp)
{
+ DebugCheck(attacker_stats == NULL);
+ DebugCheck(goal == NULL);
return CalculateDamageStats(attacker_stats, goal->Stats, bloodlust, xp);
}
@@ -511,6 +520,7 @@
Unit* goal;
Missile* missile;
+ DebugCheck(unit == NULL);
//
// Goal dead?
//
@@ -539,7 +549,7 @@
//
// No missile hits immediately!
//
- if (((MissileType*)unit->Type->Missile.Missile)->Class ==
MissileClassNone) {
+ if (unit->Type->Missile.Missile->Class == MissileClassNone) {
// No goal, take target coordinates
if (!goal) {
dx = unit->Orders[0].X;
@@ -622,6 +632,14 @@
local void GetMissileMapArea(const Missile* missile, int* sx, int* sy,
int* ex, int* ey)
{
+ DebugCheck(missile == NULL);
+ DebugCheck(sx == NULL);
+ DebugCheck(sy == NULL);
+ DebugCheck(ex == NULL);
+ DebugCheck(ey == NULL);
+ DebugCheck(TileSizeX <= 0);
+ DebugCheck(TileSizeY <= 0);
+ DebugCheck(missile->Type == NULL);
*sx = missile->X / TileSizeX;
*sy = missile->Y / TileSizeY;
*ex = (missile->X + missile->Type->Width) / TileSizeX;
@@ -643,18 +661,18 @@
int min_y;
int max_y;
+ DebugCheck(vp == NULL);
+ DebugCheck(missile == NULL);
GetMissileMapArea(missile, &min_x, &min_y, &max_x, &max_y);
if (!AnyMapAreaVisibleInViewport(vp, min_x, min_y, max_x, max_y)) {
return 0;
}
DebugLevel3Fn("Missile bounding box %d %d %d %d\n" _C_ min_x _C_ max_x _C_
min_y _C_ max_y);
-
if (!IsMapFieldVisible(ThisPlayer, (missile->X - TileSizeX / 2) /
TileSizeX,
(missile->Y - TileSizeY / 2) / TileSizeY) && !ReplayRevealMap) {
return 0;
}
-
return 1;
}
@@ -671,6 +689,7 @@
int ex;
int ey;
+ DebugCheck(missile == NULL);
GetMissileMapArea(missile, &sx, &sy, &ex, &ey);
return MarkDrawAreaMap(sx, sy, ex, ey);
}
@@ -685,6 +704,7 @@
*/
global void DrawMissile(const MissileType* mtype, int frame, int x, int y)
{
+ DebugCheck(mtype == NULL);
// FIXME: This is a hack for mirrored sprites
if (frame < 0) {
VideoDrawClipX(mtype->Sprite, -frame, x, y);
@@ -701,6 +721,9 @@
const Missile* c1;
const Missile* c2;
+ DebugCheck(v1 == NULL);
+ DebugCheck(v2 == NULL);
+
c1 = *(Missile**)v1;
c2 = *(Missile**)v2;
@@ -724,6 +747,8 @@
int flag;
int nmissiles;
+ DebugCheck(vp == NULL);
+ DebugCheck(table == NULL);
//
// Loop through global missiles, than through locals.
//
@@ -767,6 +792,7 @@
int dir;
int nextdir;
+ DebugCheck(missile == NULL);
if (missile->SpriteFrame < 0) {
missile->SpriteFrame = -missile->SpriteFrame;
}
@@ -787,6 +813,8 @@
** Handle point to point missile.
**
** @param missile Missile pointer.
+**
+** @return 1 if goal is reached, 0 else.
*/
local int PointToPointMissile(Missile* missile)
{
@@ -1109,8 +1137,6 @@
int n;
int i;
- // FIXME: should I move the PlayMissileSound to here?
-
if (missile->Type->ImpactSound.Sound) {
PlayMissileSound(missile, missile->Type->ImpactSound.Sound);
}
@@ -1122,19 +1148,16 @@
// The impact generates a new missile.
//
if (missile->Type->ImpactMissile) {
- Missile* mis;
+// Missile* mis;
- mis = MakeMissile(missile->Type->ImpactMissile, x, y, 0, 0);
+// mis =
+ MakeMissile(missile->Type->ImpactMissile, x, y, x, y);
// Impact missiles didn't generate any damage now.
#if 0
mis->Damage = missile->Damage; // direct damage, spells mostly
mis->SourceUnit = missile->SourceUnit;
// FIXME: should copy target also?
if (mis->SourceUnit) {
- // RefsDebugCheck( mis->SourceUnit->Destroyed );
- if (mis->SourceUnit->Destroyed) {
- DebugLevel0Fn("Referencing a destroyed unit, I think it is good
here\n");
- }
RefsDebugCheck(!mis->SourceUnit->Refs);
mis->SourceUnit->Refs++;
}
@@ -1185,7 +1208,7 @@
i = missile->Type->Range;
n = SelectUnits(x - i + 1, y - i + 1, x + i, y + i, table);
for (i = 0; i < n; ++i) {
- goal=table[i];
+ goal = table[i];
//
// Can the unit attack the this unit-type?
// NOTE: perhaps this should be come a property of the missile.
@@ -1220,6 +1243,44 @@
}
}
+
+/**
+** Pass to the next frame for animation.
+**
+** @param missile : missile to animate.
+** @param SpriteFrame : number of frame for a row : must be remove
+** @return 1 if animation is finished, 0 else.
+** @todo remove SpriteFrame, and use number of frames per row (frames pro
row)
+*/
+local int NextMissileFrame(Missile* missile, int SpriteFrame)
+{
+ int neg;
+ int AnimationIsFinished;
+
+ DebugCheck(missile == NULL);
+//
+// Animate missile, cycle through frames
+//
+ neg = 0;
+ AnimationIsFinished = 0;
+ if (missile->SpriteFrame < 0) {
+ neg = 1;
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ missile->SpriteFrame += SpriteFrame; // FIXME: frames pro row
+ if (missile->SpriteFrame >= VideoGraphicFrames(missile->Type->Sprite)) {
+ missile->SpriteFrame -= VideoGraphicFrames(missile->Type->Sprite);
+ AnimationIsFinished = 1;
+ }
+ if (neg) {
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ DebugLevel3Fn("Frame %d of %d\n" _C_
+ missile->SpriteFrame _C_ VideoGraphicFrames(missile->Type->Sprite));
+ return AnimationIsFinished;
+}
+
+
/**
** Handle action for a missile.
**
@@ -1227,373 +1288,56 @@
*/
local void MissileAction(Missile* missile)
{
- int neg;
-
+ DebugCheck(missile == NULL);
// Mark missile area on screen to be drawn, if missile moves or disappears.
CheckMissileToBeDrawn(missile);
+ missile->Wait = missile->Type->Sleep;
switch (missile->Type->Class) {
//
// Missile flies from x,y to x1,y1
//
case MissileClassPointToPoint:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- } else {
- //
- // Animate missile, cycle through frames
- //
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->SpriteFrame += 5; // FIXME: frames per row
- if (missile->SpriteFrame >=
VideoGraphicFrames(missile->Type->Sprite)) {
- missile->SpriteFrame-=
- VideoGraphicFrames(missile->Type->Sprite);
- }
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- DebugLevel3Fn("Frame %d of %d\n" _C_
- missile->SpriteFrame _C_
- VideoGraphicFrames(missile->Type->Sprite));
- }
+ MissileActionPointToPoint(missile);
break;
-
case MissileClassPointToPointWithDelay:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- } else {
- int totalx;
- int dx;
- int f;
- int i;
- int j;
-
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- totalx = abs(missile->DX - missile->SourceX);
- dx = abs(missile->X - missile->SourceX);
- f = VideoGraphicFrames(missile->Type->Sprite) / 5; // FIXME:
frames per row
- f = 2 * f - 1;
- for (i = 1, j = 1; i <= f; ++i) {
- if (dx * f / i < totalx) {
- if ((i - 1) * 2 < f) {
- j = i - 1;
- } else {
- j = f - i;
- }
- missile->SpriteFrame = missile->SpriteFrame % 5 +
- j * 5; // FIXME: frames per row
- break;
- }
- }
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- }
+ MissileActionPointToPointWithDelay(missile);
break;
-
case MissileClassPointToPoint3Bounces:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- //
- // 3 Bounces.
- //
- switch (missile->State) {
- case 1:
- case 3:
- case 5:
- missile->State += 2;
- missile->DX += missile->Xstep * TileSizeX * 3 / 2;
- missile->DY += missile->Ystep * TileSizeY * 3 / 2;
- MissileHit(missile);
- // FIXME: hits to left and right
- // FIXME: reduce damage effects on later impacts
- break;
- default:
- FreeMissile(missile);
- missile = NULL;
- break;
- }
- } else {
- //
- // Animate missile, cycle through frames
- //
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->SpriteFrame += 5; // FIXME: frames per row
- if (missile->SpriteFrame >=
VideoGraphicFrames(missile->Type->Sprite)) {
- missile->SpriteFrame-=
- VideoGraphicFrames(missile->Type->Sprite);
- }
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- DebugLevel3Fn("Frame %d of %d\n" _C_
- missile->SpriteFrame _C_
- VideoGraphicFrames(missile->Type->Sprite));
- }
+ MissileActionPointToPoint3Bounces(missile);
break;
-
case MissileClassPointToPointWithHit:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- //
- // Animate hit
- //
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->SpriteFrame += 5; // FIXME: frames per row
- if (missile->SpriteFrame >=
VideoGraphicFrames(missile->Type->Sprite)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- }
- break;
-
-#if 0 // FIXME: is done by the mythic controller
- case MissileClassFlameShield:
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
- missile->SpriteFrame = 0;
- if (PointToPointMissile(missile)) {
- // Must set new goal.
- }
- }
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- break;
-#endif
-
+ MissileActionPointToPointWithHit(missile);
case MissileClassBlizzard:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- //
- // Animate hit
- //
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->SpriteFrame += 4; // FIXME: frames per row
- if (missile->SpriteFrame >=
VideoGraphicFrames(missile->Type->Sprite)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile=NULL;
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- }
+ MissileActionPointToPointWithHit(missile);
break;
-
case MissileClassDeathDecay:
- //NOTE: vladi: this is exact copy of MissileClassStayWithDelay
- // but with check for blizzard-type hit (friendly fire:))
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile=NULL;
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
+ MissileActionStayWithDelay(missile);
break;
-
case MissileClassWhirlwind:
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
+ if (NextMissileFrame(missile, 1)) {
missile->SpriteFrame = 0;
PointToPointMissile(missile);
}
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
break;
-
case MissileClassStayWithDelay:
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- // FIXME: should MissileHitAndFree();
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
+ MissileActionStayWithDelay(missile);
break;
-
case MissileClassCycleOnce:
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- switch (missile->State) {
- case 0:
- case 2:
- ++missile->State;
- break;
- case 1:
- if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
- --missile->SpriteFrame;
- ++missile->State;
- }
- break;
- case 3:
- if (!missile->SpriteFrame--) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- }
- break;
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
+ MissileActionCycleOnce(missile);
break;
-
- case MissileClassFire: {
- Unit* unit;
-
- unit = missile->SourceUnit;
- if (unit->Destroyed || !unit->HP) {
- FreeMissile(missile);
- missile = NULL;
- break;
- }
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- missile->Wait = missile->Type->Sleep;
- if (++missile->SpriteFrame
==VideoGraphicFrames(missile->Type->Sprite)) {
- int f;
- MissileType* fire;
-
- missile->SpriteFrame = 0;
- f = (100 * unit->HP) / unit->Stats->HitPoints;
- fire = MissileBurningBuilding(f);
- if (!fire) {
- FreeMissile(missile);
- missile = NULL;
- unit->Burning = 0;
- } else {
- if (missile->Type != fire) {
- missile->X += missile->Type->Width / 2;
- missile->Y += missile->Type->Height / 2;
- missile->Type = fire;
- missile->X -= missile->Type->Width / 2;
- missile->Y -= missile->Type->Height / 2;
- }
- }
- }
- if (neg && missile) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
+ case MissileClassFire:
+ MissileActionFire(missile);
break;
-
case MissileClassHit:
- missile->Wait = missile->Type->Sleep;
- if (PointToPointMissile(missile)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- }
+ MissileActionHit(missile);
break;
- }
-
case MissileClassParabolic:
- missile->Wait = missile->Type->Sleep;
- if (ParabolicMissile(missile)) {
- MissileHit(missile);
- FreeMissile(missile);
- missile = NULL;
- } else {
- int totalx;
- int dx;
- int f;
- int i;
- int j;
-
- neg = 0;
- if (missile->SpriteFrame < 0) {
- neg = 1;
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- totalx = abs(missile->DX - missile->SourceX);
- dx = abs(missile->X - missile->SourceX);
- f = VideoGraphicFrames(missile->Type->Sprite) / 5; // FIXME:
frames per row
- f = 2 * f - 1;
- for (i = 1, j = 1; i <= f; ++i) {
- if (dx * f / i < totalx) {
- if ((i - 1) * 2 < f) {
- j = i - 1;
- } else {
- j = f - i;
- }
- missile->SpriteFrame = missile->SpriteFrame % 5 +
- j * 5; // FIXME: frames per row
- break;
- }
- }
- if (neg) {
- missile->SpriteFrame = -missile->SpriteFrame;
- }
- }
+ MissileActionParabolic(missile);
+ break;
+ case MissileClassLandMine:
+ MissileActionLandMine(missile);
break;
- }
-
- if (missile) { // check after movement
- CheckMissileToBeDrawn(missile);
}
}
@@ -1610,6 +1354,8 @@
// NOTE: missiles[??] could be modified!!!
//
while ((missile = *missiles)) {
+ DebugLevel3Fn("Missile %s ttl %d at %d, %d\n" _C_ missile->Type->Ident
+ _C_ missile->TTL _C_ missile->X _C_ missile->Y);
if (missile->Delay && missile->Delay--) {
++missiles;
continue; // delay start of missile
@@ -1644,7 +1390,7 @@
MissileAction(missile);
- if (*missiles == missile) { // Missile not destoryed
+ if (*missiles == missile) { // Missile not destroyed
++missiles;
}
}
@@ -1669,6 +1415,7 @@
int x;
int y;
+ DebugCheck(missile == NULL);
x = (missile->X+missile->Type->Width / 2) / TileSizeX;
y = (missile->Y+missile->Type->Height / 2) / TileSizeY; // pixel -> tile
@@ -1712,7 +1459,7 @@
int i;
CLprintf(file,"\n;;; -----------------------------------------\n");
- CLprintf(file,";;; MODULE: missile-types $Id: missile.c,v 1.90 2003/10/12
16:18:12 n0body Exp $\n\n");
+ CLprintf(file,";;; MODULE: missile-types $Id: missile.c,v 1.91 2003/10/13
11:21:08 n0body Exp $\n\n");
//
// Original number to internal missile-type name.
@@ -1807,7 +1554,7 @@
Missile* const* missiles;
CLprintf(file,"\n;;; -----------------------------------------\n");
- CLprintf(file,";;; MODULE: missiles $Id: missile.c,v 1.90 2003/10/12
16:18:12 n0body Exp $\n\n");
+ CLprintf(file,";;; MODULE: missiles $Id: missile.c,v 1.91 2003/10/13
11:21:08 n0body Exp $\n\n");
for (missiles = GlobalMissiles; *missiles; ++missiles) {
SaveMissile(*missiles, file);
@@ -1843,8 +1590,6 @@
mtype->ImpactMissile = MissileTypeByIdent(mtype->ImpactName);
}
}
-
- MissileTypeExplosion = MissileTypeByIdent("missile-explosion");
}
/**
@@ -1903,6 +1648,572 @@
}
free(MissileTypeWcNames);
MissileTypeWcNames = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------------
+-- Functions (Spells Controllers/Callbacks) TODO move to anoher file?
+----------------------------------------------------------------------------*/
+
+// ****************************************************************************
+// Actions for the missiles
+// ****************************************************************************
+
+/*
+** Missile controllers
+**
+** To cancel a missile set it's TTL to 0, it will be handled right after
+** the controller call and missile will be down.
+**
+*/
+
+/*
+** Missile does nothing
+**
+** @param missile pointer to missile
+*/
+void MissileActionNone(Missile* missile)
+{
+ return;// Busy doing nothing.
+}
+
+/*
+** Missile flies from x,y to x1,y1
+**
+** @param missile pointer to missile
+*/
+void MissileActionPointToPoint(Missile* missile)
+{
+ if (PointToPointMissile(missile)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ } else {
+ NextMissileFrame(missile, 5);
+ }
+}
+
+/*
+** Missile flies from x,y to x1,y1 and stays there for a moment
+**
+** @param missile pointer to missile
+*/
+void MissileActionPointToPointWithDelay(Missile* missile)
+{
+ int neg;
+ int totalx;
+ int dx;
+ int f;
+ int i;
+ int j;
+
+ if (PointToPointMissile(missile)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ } else {
+ neg = 0;
+ if (missile->SpriteFrame < 0) {
+ neg = 1;
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ totalx = abs(missile->DX - missile->SourceX);
+ dx = abs(missile->X - missile->SourceX);
+ f = VideoGraphicFrames(missile->Type->Sprite) / 5; // FIXME: frames per
row
+ f = 2 * f - 1;
+ for (i = 1, j = 1; i <= f; ++i) {
+ if (dx * f / i < totalx) {
+ if ((i - 1) * 2 < f) {
+ j = i - 1;
+ } else {
+ j = f - i;
+ }
+ missile->SpriteFrame = missile->SpriteFrame % 5 +
+ j * 5; // FIXME: frames per row
+ break;
+ }
+ }
+ if (neg) {
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ }
+}
+
+/*
+** Missile don't move, than disappears
+**
+** @param missile pointer to missile
+*/
+void MissileActionStayWithDelay(Missile* missile)
+{
+ if (NextMissileFrame(missile, 1)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ }
+}
+
+/**
+** Missile flies from x,y to x1,y1 than bounces three times.
+**
+** @param missile pointer to missile
+*/
+void MissileActionPointToPoint3Bounces(Missile* missile)
+{
+ if (PointToPointMissile(missile)) {
+ // 3 Bounces.
+ switch (missile->State) {
+ case 1:
+ case 3:
+ case 5:
+ missile->State += 2;
+ missile->DX += missile->Xstep * TileSizeX * 3 / 2;
+ missile->DY += missile->Ystep * TileSizeY * 3 / 2;
+ MissileHit(missile);
+ // FIXME: hits to left and right
+ // FIXME: reduce damage effects on later impacts
+ break;
+ default:
+ FreeMissile(missile);
+ missile = NULL;
+ break;
+ }
+ } else {
+ NextMissileFrame(missile, 5);
+ }
+}
+
+void MissileActionCycleOnce(Missile* missile)
+{
+ int neg;
+
+ neg = 0;
+ if (missile->SpriteFrame < 0) {
+ neg = 1;
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ switch (missile->State) {
+ case 0:
+ case 2:
+ ++missile->State;
+ break;
+ case 1:
+ if (++missile->SpriteFrame ==
VideoGraphicFrames(missile->Type->Sprite)) {
+ --missile->SpriteFrame;
+ ++missile->State;
+ }
+ break;
+ case 3:
+ if (!missile->SpriteFrame--) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ missile = NULL;
+ }
+ break;
+ }
+ if (neg && missile) {
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+}
+
+/*
+** Missile flies from x,y to x1,y1 than shows hit animation.
+**
+** @param missile pointer to missile
+*/
+void MissileActionPointToPointWithHit(Missile* missile)
+{
+ if (PointToPointMissile(missile)) {
+ if (NextMissileFrame(missile, 4)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ }
+ }
+}
+
+/*
+** Missile don't move, than checks the source unit for HP.
+**
+** @param missile pointer to missile
+*/
+void MissileActionFire(Missile* missile)
+{
+ Unit* unit;
+
+ unit = missile->SourceUnit;
+ if (unit->Destroyed || !unit->HP) {
+ FreeMissile(missile);
+ return;
+ }
+ if (NextMissileFrame(missile, 1)) {
+ int f;
+ MissileType* fire;
+
+ missile->SpriteFrame = 0;
+ f = (100 * unit->HP) / unit->Stats->HitPoints;
+ fire = MissileBurningBuilding(f);
+ if (!fire) {
+ FreeMissile(missile);
+ missile = NULL;
+ unit->Burning = 0;
+ } else {
+ if (missile->Type != fire) {
+ missile->X += missile->Type->Width / 2;
+ missile->Y += missile->Type->Height / 2;
+ missile->Type = fire;
+ missile->X -= missile->Type->Width / 2;
+ missile->Y -= missile->Type->Height / 2;
+ }
+ }
+ }
+}
+
+void MissileActionHit(Missile* missile)
+{
+ if (PointToPointMissile(missile)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ }
+}
+
+/*
+** Missile flies from x,y to x1,y1 using a parabolic path
+**
+** @param missile pointer to missile
+*/
+void MissileActionParabolic(Missile* missile)
+{
+ int neg;
+
+ if (ParabolicMissile(missile)) {
+ MissileHit(missile);
+ FreeMissile(missile);
+ missile = NULL;
+ } else {
+ int totalx;
+ int dx;
+ int f;
+ int i;
+ int j;
+
+ neg = 0;
+ if (missile->SpriteFrame < 0) {
+ neg = 1;
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ totalx = abs(missile->DX - missile->SourceX);
+ dx = abs(missile->X - missile->SourceX);
+ f = VideoGraphicFrames(missile->Type->Sprite) / 5; // FIXME: frames per
row
+ f = 2 * f - 1;
+ for (i = 1, j = 1; i <= f; ++i) {
+ if (dx * f / i < totalx) {
+ if ((i - 1) * 2 < f) {
+ j = i - 1;
+ } else {
+ j = f - i;
+ }
+ missile->SpriteFrame = missile->SpriteFrame % 5 +
+ j * 5; // FIXME: frames per row
+ break;
+ }
+ }
+ if (neg) {
+ missile->SpriteFrame = -missile->SpriteFrame;
+ }
+ }
+}
+
+/**
+** Death-Coil controller
+**
+** @param missile Controlled missile
+*/
+global void SpellDeathCoilController(Missile *missile)
+{
+ Unit *table[UnitMax];
+ int i;
+ int n;
+ Unit *source;
+
+ DebugCheck(missile == NULL);
+ //
+ // missile has not reached target unit/spot
+ //
+ if (!(missile->X == missile->DX && missile->Y == missile->DY)) {
+ return ;
+ }
+ source = missile->SourceUnit;
+ if (source->Destroyed) {
+ return ;
+ }
+ // source unit still exists
+ //
+ // Target unit still exists and casted on a special target
+ //
+ if (missile->TargetUnit && !missile->TargetUnit->Destroyed
+ && missile->TargetUnit->HP) {
+ if (missile->TargetUnit->HP <= 50) {// 50 should be parametrable
+ source->Player->Score += missile->TargetUnit->Type->Points;
+ if( missile->TargetUnit->Type->Building) {
+ source->Player->TotalRazings++;
+ } else {
+ source->Player->TotalKills++;
+ }
+#ifdef USE_HP_FOR_XP
+ source->XP += missile->TargetUnit->HP;
+#else
+ source->XP += missile->TargetUnit->Type->Points;
+#endif
+ ++source->Kills;
+ missile->TargetUnit->HP = 0;
+ LetUnitDie(missile->TargetUnit);
+ } else {
+#ifdef USE_HP_FOR_XP
+ source->XP += 50;
+#endif
+ missile->TargetUnit->HP -= 50;
+ }
+ if (source->Orders[0].Action != UnitActionDie) {
+ source->HP += 50;
+ if (source->HP > source->Stats->HitPoints) {
+ source->HP = source->Stats->HitPoints;
+ }
+ }
+ } else {
+ //
+ // No target unit -- try enemies in range 5x5 // Must be parametrable
+ //
+ int ec; // enemy count
+ int x;
+ int y;
+
+ ec = 0;
+ x = missile->DX / TileSizeX;
+ y = missile->DY / TileSizeY;
+
+ n = SelectUnits(x - 2, y - 2, x + 2, y + 2, table);
+ if (n == 0) {
+ return ;
+ }
+ // calculate organic enemy count
+ for (i = 0; i < n; ++i) {
+ ec += (IsEnemy(source->Player, table[i])
+ && table[i]->Type->Organic != 0);
+ }
+ if (ec > 0) {
+ // yes organic enemies found
+ for (i = 0; i < n; ++i) {
+ if (IsEnemy(source->Player, table[i]) &&
table[i]->Type->Organic != 0) {
+ // disperse damage between them
+ //NOTE: 1 is the minimal damage
+ if (table[i]->HP <= 50 / ec ) {
+ source->Player->Score += table[i]->Type->Points;
+ if( table[i]->Type->Building ) {
+ source->Player->TotalRazings++;
+ } else {
+ source->Player->TotalKills++;
+ }
+#ifdef USE_HP_FOR_XP
+ source->XP += table[i]->HP;
+#else
+ source->XP += table[i]->Type->Points;
+#endif
+ ++source->Kills;
+ table[i]->HP = 0;
+ LetUnitDie(table[i]); // too much damage
+ } else {
+#ifdef USE_HP_FOR_XP
+ source->XP += 50/ec;
+#endif
+ table[i]->HP -= 50 / ec;
+ }
+ }
+ }
+ if (source->Orders[0].Action!=UnitActionDie) {
+ source->HP += 50;
+ if (source->HP > source->Stats->HitPoints) {
+ source->HP = source->Stats->HitPoints;
+ }
+ }
+ }
+ }
+}
+
+/**
+** Fireball controller
+**
+** @param missile Controlled missile
+*/
+global void SpellFireballController(Missile *missile)
+{
+ DebugCheck(missile == NULL);
+ //NOTE: vladi: TTL is used as counter for explosions
+ // explosions start at target and continue (10 tiles) beyond
+ // explosions are on each tile on the way
+
+ // approx
+ if (missile->TTL <= missile->State && missile->TTL % 4 == 0) {
+ MissileHit(missile);
+ }
+}
+
+/**
+** FlameShield controller
+**
+** @param missile Controlled missile
+*/
+global void SpellFlameShieldController(Missile *missile)
+{
+ static int fs_dc[] = {
+ 0, 32, 5, 31, 10, 30, 16, 27, 20, 24, 24, 20, 27, 15, 30, 10, 31,
+ 5, 32, 0, 31, -5, 30, -10, 27, -16, 24, -20, 20, -24, 15, -27, 10,
+ -30, 5, -31, 0, -32, -5, -31, -10, -30, -16, -27, -20, -24, -24, -20,
+ -27, -15, -30, -10, -31, -5, -32, 0, -31, 5, -30, 10, -27, 16, -24,
+ 20, -20, 24, -15, 27, -10, 30, -5, 31, 0, 32};
+ Unit *table[UnitMax];
+ int n;
+ int i;
+ int dx;
+ int dy;
+ int ux;
+ int uy;
+ int ix;
+ int iy;
+ int uw;
+ int uh;
+
+ DebugCheck(missile == NULL);
+ i = missile->TTL % 36; // 36 positions on the circle
+ dx = fs_dc[i * 2];
+ dy = fs_dc[i * 2 + 1];
+ ux = missile->TargetUnit->X;
+ uy = missile->TargetUnit->Y;
+ ix = missile->TargetUnit->IX;
+ iy = missile->TargetUnit->IY;
+ uw = missile->TargetUnit->Type->Width;
+ uh = missile->TargetUnit->Type->Height;
+ missile->X = ux * TileSizeX + ix + uw / 2 + dx - 32;
+ missile->Y = uy * TileSizeY + iy + uh / 2 + dy - 32 - 16;
+ if (missile->TargetUnit->Orders[0].Action == UnitActionDie) {
+ missile->TTL = i;
+ }
+ if (missile->TTL == 0) {
+ missile->TargetUnit->FlameShield = 0;
+ }
+ //vladi: still no have clear idea what is this about :)
+ CheckMissileToBeDrawn(missile);
+
+ // Only hit 1 out of 8 frames
+ if (missile->TTL & 7) {
+ return;
+ }
+ n = SelectUnits(ux - 1, uy - 1, ux + 1 + 1, uy + 1 + 1, table);
+ for (i = 0; i < n; ++i) {
+ if (table[i] == missile->TargetUnit) {
+ // cannot hit target unit
+ continue;
+ }
+ if (table[i]->HP) {
+ HitUnit(missile->SourceUnit, table[i], missile->Damage);
+ }
+ }
+}
+
+/**
+** Runes controller
+**
+** @param missile Controlled missile
+*/
+global void MissileActionLandMine(Missile *missile)
+{
+ Unit *table[UnitMax];
+ int i;
+ int n;
+ int x;
+ int y;
+
+ DebugCheck(missile == NULL);
+ DebugCheck(TileSizeX == 0);
+ DebugCheck(TileSizeY == 0);
+
+ x = missile->X / TileSizeX;
+ y = missile->Y / TileSizeY;
+
+ n = SelectUnitsOnTile(x, y, table);
+ for (i = 0; i < n; ++i) {
+ if (table[i]->Type->UnitType != UnitTypeFly &&
+ table[i]->HP &&
+ table[i]!=missile->SourceUnit) {
+ DebugLevel0("Landmine explosion.\n");
+ MissileHit(missile);
+ missile->TTL = 0;
+ return;
+ }
+ }
+
+ NextMissileFrame(missile, 1);
+}
+
+/**
+** Whirlwind controller
+**
+** @param missile Controlled missile
+*/
+global void SpellWhirlwindController(Missile *missile)
+{
+ Unit *table[UnitMax];
+ int i;
+ int n;
+ int x;
+ int y;
+
+ DebugCheck(missile == NULL);
+ //
+ // Center of the tornado
+ //
+ x = (missile->X+TileSizeX/2+missile->Type->Width/2) / TileSizeX;
+ y = (missile->Y+TileSizeY+missile->Type->Height/2) / TileSizeY;
+ //
+ // Every 4 cycles 4 points damage in tornado center
+ //
+ if (!(missile->TTL % 4)) {
+ n = SelectUnitsOnTile(x, y, table);
+ for (i = 0; i < n; ++i) {
+ if (table[i]->HP) {
+ HitUnit(missile->SourceUnit,table[i], WHIRLWIND_DAMAGE1);//
should be missile damage ?
+ }
+ }
+ }
+ //
+ // Every 1/10s 1 points damage on tornado periphery
+ //
+ if (!(missile->TTL % (CYCLES_PER_SECOND/10))) {
+ // we should parameter this
+ n = SelectUnits(x - 1, y - 1, x + 1, y + 1, table);
+ DebugLevel3Fn("Damage on %d,%d-%d,%d = %d\n" _C_ x-1 _C_ y-1 _C_ x+1
_C_ y+1 _C_ n);
+ for (i = 0; i < n; ++i) {
+ if( (table[i]->X != x || table[i]->Y != y) && table[i]->HP) {
+ HitUnit(missile->SourceUnit,table[i], WHIRLWIND_DAMAGE2); //
should be in missile
+ }
+ }
+ }
+ DebugLevel3Fn( "Whirlwind: %d, %d, TTL: %d\n" _C_
+ missile->X _C_ missile->Y _C_ missile->TTL );
+
+ //
+ // Changes direction every 3 seconds (approx.)
+ //
+ if (!(missile->TTL % 100)) { // missile has reached target unit/spot
+ int nx;
+ int ny;
+
+ do {
+ // find new destination in the map
+ nx = x + SyncRand() % 5 - 2;
+ ny = y + SyncRand() % 5 - 2;
+ } while (nx < 0 && ny < 0 && nx >= TheMap.Width && ny >= TheMap.Height);
+ missile->DX = nx * TileSizeX + TileSizeX / 2;
+ missile->DY = ny * TileSizeY + TileSizeY / 2;
+ missile->State=0;
+ DebugLevel3Fn( "Whirlwind new direction: %d, %d, TTL: %d\n" _C_
+ missile->X _C_ missile->Y _C_ missile->TTL );
}
}