[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stratagus-CVS] stratagus data/ccl/spells.ccl src/action/action...
From: |
Crestez Leonard |
Subject: |
[Stratagus-CVS] stratagus data/ccl/spells.ccl src/action/action... |
Date: |
Fri, 26 Sep 2003 11:47:51 -0400 |
CVSROOT: /cvsroot/stratagus
Module name: stratagus
Branch:
Changes by: Crestez Leonard <address@hidden> 03/09/26 11:47:51
Modified files:
data/ccl : spells.ccl
src/action : action_resource.c
src/ai : ai_magic.c
src/clone : ccl_spell.c spells.c
src/include : spells.h
src/siod : slib.c
Log message:
Spell work.
Patches:
Index: stratagus/data/ccl/spells.ccl
diff -u stratagus/data/ccl/spells.ccl:1.1 stratagus/data/ccl/spells.ccl:1.2
--- stratagus/data/ccl/spells.ccl:1.1 Mon Sep 22 15:13:07 2003
+++ stratagus/data/ccl/spells.ccl Fri Sep 26 11:47:50 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.1 2003/09/22 19:13:07 n0body Exp $
+;; $Id: spells.ccl,v 1.2 2003/09/26 15:47:50 n0body Exp $
;; For documentation see stratagus/doc/ccl/ccl.html ;; FIXME write and move
doc.
@@ -108,7 +108,7 @@
'manacost 6
'range 6
'target 'unit
- 'action '( Healing (HP 1) )
+ 'action '( healing (HP 1) )
'condition '( UnitTypeflag (true organic)
UnitTypeflag (false building)
DurationEffect (false flag HP_percent value 100) ;; HP
< 100% HPMAX
@@ -127,7 +127,7 @@
'manacost 4
'range 10
'target 'unit
- 'action '( Healing (HP -1) )
+ 'action '( healing (HP -1) )
'condition '( UnitTypeflag (true undead)
UnitTypeflag (false building)
Alliance false
@@ -153,7 +153,7 @@
'manacost 50
'range 6
'target 'unit
- 'action '( Haste (haste 1000 slow 0) )
+ 'action '( haste (haste 1000 slow 0) )
'condition '( UnitTypeflag (false building)
DurationEffect (false flag haste value 900) ;; haste <
900 / CYCLE_PER_SECOND
Alliance true
@@ -168,7 +168,7 @@
'manacost 50
'range 10
'target 'unit
- 'action '( Haste (slow 1000 haste 0) )
+ 'action '( haste (slow 1000 haste 0) )
'condition '( UnitTypeflag (false building)
DurationEffect (false flag slow value 900) ;; slow <
900 / CYCLE_PER_SECOND
Alliance true
@@ -183,7 +183,7 @@
'manacost 50
'range 6
'target 'unit
- 'action '( Haste (bloodlust 1000) )
+ 'action '( haste (bloodlust 1000) )
'condition '( UnitTypeflag (true organic)
DurationEffect (false flag bloodlust value 900) ;;
bloodlust < 900 / CYCLE_PER_SECOND
Alliance true
@@ -228,13 +228,13 @@
'manacost 50
'range 6
'target 'unit
- 'action '( FlameShield (ttl 600))
+ 'action '( flame-shield (ttl 600))
'condition '(UnitTypeflag (false building)
DurationEffect (false flag flameshield value 500) ;;
flameshield < 900 / CYCLE_PER_SECOND
;; Alliance false;; On which player (true own , false
opponents)
);; FIXME
'sound-when-cast "flame shield"
-;; 'missile-when-cast "missile-flame-shield" ; NOT use
+ 'missile-when-cast "missile-flame-shield" ; NOT use
'autocast '(range 6 condition (UnitTypeflag (false coward)))
)
@@ -258,7 +258,13 @@
'manacost 25
'range 12
'target 'position
- 'action '( Blizzard (fields 5 shards 10 damage 10) )
+ 'action '(area-bombardment
+ (fields 5
+ shards 10
+ damage 10
+ ;; 128=4*32=4 tiles
+ start-offset-x -128
+ start-offset-y -128))
'sound-when-cast "blizzard"
'missile-when-cast "missile-blizzard"
;; 'autocast '(range 12)
@@ -269,7 +275,7 @@
'manacost 25
'range 12
'target 'position
- 'action '( DeathAndDecay (fields 5 shards 10 damage 10) )
+ 'action '(area-bombardment (fields 5 shards 10 damage 10) )
'sound-when-cast "death and decay"
'missile-when-cast "missile-death-and-decay"
;; 'autocast '(range 12)
@@ -280,7 +286,7 @@
'manacost 100
'range 8
'target 'position
- 'action '( FireBall (ttl 1000 damage 20))
+ 'action '( fireball (ttl 1000 damage 20))
'sound-when-cast "fireball throw"
'missile-when-cast "missile-fireball"
;; 'autocast '(range 8)
@@ -302,7 +308,7 @@
'manacost 100
'range 10
'target 'position ;; FIXME position or organic target
- 'action '( DeathCoil )
+ 'action '( death-coil )
;; 'condition '(UnitTypeflag (true organic))
'sound-when-cast "death coil"
'missile-when-cast "missile-death-coil"
@@ -336,20 +342,9 @@
'manacost 25
'range -1
'target 'position
- 'action '( CircleOfPower "unit-circle-of-power" )
+ 'action '( spawn-portal "unit-circle-of-power" )
'sound-when-cast "circle of power"
'missile-when-cast "missile-normal-spell"
;; 'autocast '(range -1)
)
-;(define-caster 'caster "unit-paladin" 'spell "spell-holy-vision"
"spell-healing" "spell-exorcism")
-;(define-caster 'caster "unit-mage"
-; 'spell "spell-fireball" "spell-slow" "spell-flame-shield"
"spell-invisibility"
-; "spell-polymorph" "spell-blizzard")
-;(define-caster 'caster "unit-ogre-mage" 'spell "spell-eye-of-vision"
"spell-bloodlust" "spell-runes")
-;(define-caster 'caster "unit-death-knight"
-; 'spell "spell-death-coil" "spell-haste" "spell-raise-dead"
"spell-whirlwind"
-; "spell-unholy-armor" "spell-death-and-decay")
-
-;(define-caster 'caster ""
-; 'spell "spell-circle-of-power")
Index: stratagus/src/action/action_resource.c
diff -u stratagus/src/action/action_resource.c:1.55
stratagus/src/action/action_resource.c:1.56
--- stratagus/src/action/action_resource.c:1.55 Sun Sep 14 00:45:52 2003
+++ stratagus/src/action/action_resource.c Fri Sep 26 11:47:50 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: action_resource.c,v 1.55 2003/09/14 04:45:52 mr-russ Exp $
+// $Id: action_resource.c,v 1.56 2003/09/26 15:47:50 n0body Exp $
//@{
@@ -708,7 +708,8 @@
*/
global void HandleActionResource(Unit* unit)
{
- int ret,newres;
+ int ret;
+ int newres;
DebugLevel3Fn("%s(%d) SubAction %d TTH %d res %s goal %ul\n"
_C_ unit->Type->Ident _C_ UnitNumber(unit) _C_ unit->SubAction
Index: stratagus/src/ai/ai_magic.c
diff -u stratagus/src/ai/ai_magic.c:1.15 stratagus/src/ai/ai_magic.c:1.16
--- stratagus/src/ai/ai_magic.c:1.15 Thu Sep 25 02:58:35 2003
+++ stratagus/src/ai/ai_magic.c Fri Sep 26 11:47:50 2003
@@ -10,7 +10,7 @@
//
/address@hidden ai_magic.c - AI magic functions. */
//
-// (c) Copyright 2002 by Lutz Sammer
+// (c) Copyright 2002-2003 by Lutz Sammer, Joris Dauphin
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -26,7 +26,9 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: ai_magic.c,v 1.15 2003/09/25 06:58:35 mr-russ Exp $
+// $Id: ai_magic.c,v 1.16 2003/09/26 15:47:50 n0body Exp $
+
+#ifdef NEW_AI // {
//@{
@@ -47,365 +49,47 @@
#include "ai_local.h"
/*----------------------------------------------------------------------------
--- Variables
-----------------------------------------------------------------------------*/
-
-local UnitType* AiPaladin;
-local SpellType* AiHolyVision;
-local SpellType* AiHealing;
-local UnitType* AiMage;
-local SpellType* AiSlow;
-local SpellType* AiInvisibility;
-local UnitType* AiOgreMage;
-local SpellType* AiEyeOfVision;
-local SpellType* AiBloodlust;
-local UnitType* AiUnitTypeEyeOfVision;
-local UnitType* AiDeathKnight;
-local SpellType* AiHaste;
-local SpellType* AiUnholyArmor;
-
-/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
/**
-** Init the magic.
-**
-** @note I will remove the hardcoded stuff, if tested.
-*/
-local void AiInitMagic(void)
-{
- AiPaladin=UnitTypeByIdent("unit-paladin");
- AiHolyVision=SpellTypeByIdent("spell-holy-vision");
- AiHealing=SpellTypeByIdent("spell-healing");
- AiMage=UnitTypeByIdent("unit-mage");
- AiSlow=SpellTypeByIdent("spell-slow");
- AiInvisibility=SpellTypeByIdent("spell-invisibility");
- AiOgreMage=UnitTypeByIdent("unit-ogre-mage");
- AiEyeOfVision=SpellTypeByIdent("spell-eye-of-vision");
- AiBloodlust=SpellTypeByIdent("spell-bloodlust");
- AiUnitTypeEyeOfVision=UnitTypeByIdent("unit-eye-of-vision");
- AiDeathKnight=UnitTypeByIdent("unit-death-knight");
- AiHaste=SpellTypeByIdent("spell-haste");
- AiUnholyArmor=SpellTypeByIdent("spell-unholy-armor");
-/*
- "spell-exorcism"
- "spell-fireball"
- "spell-flame-shield"
- "spell-polymorph"
- "spell-blizzard"
-
- "spell-runes"
- "spell-death-coil"
- "spell-raise-dead"
- "spell-whirlwind"
- "spell-death-and-decay"
-*/
-}
-
-/**
-** Check if the unit should cast the "bloodlust" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any enemy units are in sight. If enemy units
-** are in sight the spell is casted on own units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiBloodlustSpell(Unit* unit)
-{
- if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-bloodlust") ) {
- if( AutoCastSpell(unit,AiBloodlust) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Check if the unit should cast the "eye of vision" spell.
-**
-** If the unit has nothing to do and the spell is available and the unit
-** has full mana cast with a change of 1/32 the spell. The spells does
-** nothing, because the AI cheats and already knows the surroundings.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiEyeOfVisionSpell(Unit* unit)
-{
- if( unit->Orders[0].Action==UnitActionStill
- && UpgradeIdentAvailable(AiPlayer->Player,"upgrade-eye-of-kilrogg")
- && UpgradeIdentAvailable(AiPlayer->Player,"upgrade-ogre-mage") ) {
- // s0m3body: each unit can have different MaxMana, the original
- // condition is testing MaxMana-10, so let's take unit's
- // maxmana * 245/255 as a new threshold
- if( unit->Mana>(unit->Type->_MaxMana*245)/255 && !SyncRand()%32 ) {
- if( AutoCastSpell(unit,AiEyeOfVision) ) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-/**
-** Do magic for ogre-mage.
-*/
-local void AiDoOgreMage(Unit* unit)
-{
- if( AiBloodlustSpell(unit) ) {
- return;
- }
- if( AiEyeOfVisionSpell(unit) ) {
- return;
- }
-}
-
-/**
-** Check if the unit should cast the "slow" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any enemy units are in sight. If enemy units
-** are in sight the spell is casted on the units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiSlowSpell(Unit* unit)
-{
- if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-slow") ) {
- if( !SyncRand()%4 && AutoCastSpell(unit,AiSlow) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Check if the unit should cast the "invisibility" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any enemy units are in sight. If enemy units
-** are in sight the spell is casted on own units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiInvisibilitySpell(Unit* unit)
-{
- if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-invisibility") ) {
- if( !SyncRand()%4 && AutoCastSpell(unit,AiInvisibility) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Do magic for mage.
-*/
-local void AiDoMage(Unit* unit)
-{
- if (AiSlowSpell(unit)) {
- return;
- }
- if (AiInvisibilitySpell(unit)) {
- return;
- }
-}
-
-/**
-** Check if the unit should cast the "healing" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any ally damaged units are in sight. If ally
-** damaged units are in sight the spell is casted on own units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiHealingSpell(Unit* unit)
-{
- if (UpgradeIdentAvailable(AiPlayer->Player, "upgrade-healing") ) {
- if( AutoCastSpell(unit,AiHealing) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Check if the unit should cast the "holy vision" spell.
-**
-** If the unit has nothing to do and the spell is available and the unit
-** has full mana cast with a change of 1/32 the spell. The spells does
-** nothing, because the AI cheats and already knows the surroundings.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiHolyVisionSpell(Unit* unit)
-{
- if( unit->Orders[0].Action==UnitActionStill
- && UpgradeIdentAvailable(AiPlayer->Player,"upgrade-holy-vision")
- && UpgradeIdentAvailable(AiPlayer->Player,"upgrade-paladin") ) {
- // s0m3body: each unit can have different MaxMana, the original
- // condition is testing MaxMana-10, so let's take unit's
- // maxmana * 245/255 as a new threshold
- if( unit->Mana>(unit->Type->_MaxMana*245)/255 && !SyncRand()%32 ) {
- if( AutoCastSpell(unit,AiHolyVision) ) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-/**
-** Do magic for paladin.
-*/
-local void AiDoPaladin(Unit* unit)
-{
- if (AiHealingSpell(unit)) {
- return;
- }
- if (AiHolyVisionSpell(unit)) {
- return;
- }
-}
-
-/**
-** Check if the unit should cast the "haste" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any ally units are in sight. If ally units
-** are in sight the spell is casted on the units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiHasteSpell(Unit* unit)
-{
- if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-haste") ) {
- if( !SyncRand()%4 && AutoCastSpell(unit,AiHaste) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Check if the unit should cast the "unholy armor" spell.
-**
-** If the spell is available and the unit has enough mana, the surrounding
-** of the unit is checked if any enemy units are in sight. If enemy units
-** are in sight the spell is casted on own units in range.
-**
-** @param unit Magic unit.
-**
-** @return True, if a spell is casted.
-*/
-local int AiUnholyArmorSpell(Unit* unit)
-{
- if( UpgradeIdentAvailable(AiPlayer->Player,"upgrade-unholy-armor") ) {
- if( !SyncRand()%4 && AutoCastSpell(unit,AiUnholyArmor) ) {
- return 1;
- }
- }
- return 0;
-}
-
-/**
-** Do magic for death knight.
-*/
-local void AiDoDeathKnight(Unit* unit)
-{
- if (AiHasteSpell(unit)) {
- return;
- }
- if (AiUnholyArmorSpell(unit)) {
- return;
- }
-}
-
-/**
** Check what computer units can do with magic.
+** In fact, turn on autocast for AI.
*/
global void AiCheckMagic(void)
{
- int i;
+ int i, j;
int n;
Unit** units;
Unit* unit;
-
- AiInitMagic();
-
- n=AiPlayer->Player->TotalNumUnits;
- units=AiPlayer->Player->Units;
- for( i=0; i<n; ++i ) {
- unit=units[i];
- if( unit->Type->CanCastSpell ) { // Its a magic unit
- DebugLevel3Fn("Have mage `%s'\n" _C_ unit->Type->Ident);
- // FIXME: I hardcode the reactions now
- if( unit->Type==AiOgreMage ) {
- AiDoOgreMage(unit);
- } else if( unit->Type==AiMage ) {
- AiDoMage(unit);
- } else if( unit->Type==AiPaladin ) {
- AiDoPaladin(unit);
- } else if( unit->Type==AiDeathKnight ) {
- AiDoDeathKnight(unit);
- }
- }
- //
- // Handle casted eyes of vision.
- //
- if( unit->Type==AiUnitTypeEyeOfVision ) {
- if( unit->Orders[0].Action==UnitActionStill ) {
- int x;
- int y;
- int r;
-
- // Let it move around randomly
- r=SyncRand()>>4;
- if( r&0x20 ) {
- if( unit->X<(r&0x1F) ) {
- x=0;
- } else {
- x=unit->X-(r&0x1F);
- }
- } else {
- x=unit->X+(r&0x1F);
- if( x>=TheMap.Width ) {
- x=TheMap.Width-1;
- }
- }
- r>>=6;
- if( r&0x20 ) {
- if( unit->Y<(r&0x1F) ) {
- y=0;
- } else {
- y=unit->Y-(r&0x1F);
- }
- } else {
- y=unit->Y+(r&0x1F);
- if( y>=TheMap.Height ) {
- y=TheMap.Height-1;
- }
+ const Player *player;
+#ifdef DEBUG
+ int success;
+#endif
+
+ n = AiPlayer->Player->TotalNumUnits;
+ units = AiPlayer->Player->Units;
+ player = AiPlayer->Player;/*units[0]->Player*/
+ for(i = 0; i < n; ++i) {
+ unit = units[i];
+ // Check only magic units
+ if(unit->Type->CanCastSpell) {
+ for (j = 0; j < SpellTypeCount; j++) {
+ // Check if we can cast this spell. SpellIsAvailable checks
for upgrades.
+ if (unit->Type->CanCastSpell[j] && SpellIsAvailable(player, j))
{
+#ifdef DEBUG
+ success = // Follow on next line (AutoCastSpell).
+#endif
+ AutoCastSpell(unit, SpellTypeById(j));
+ DebugLevel3Fn("Mage '%s' cast '%s' : %s\n"
+ _C_ unit->Type->Ident
+ _C_ SpellTypeById(j)->Ident
+ _C_ success ? "success" : "fail");
}
- CommandMove(unit,x,y,FlushCommands);
}
}
}
}
//@}
+#endif // } NEW_AI
Index: stratagus/src/clone/ccl_spell.c
diff -u stratagus/src/clone/ccl_spell.c:1.4 stratagus/src/clone/ccl_spell.c:1.5
--- stratagus/src/clone/ccl_spell.c:1.4 Tue Sep 23 21:56:53 2003
+++ stratagus/src/clone/ccl_spell.c Fri Sep 26 11:47:50 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: ccl_spell.c,v 1.4 2003/09/24 01:56:53 n0body Exp $
+// $Id: ccl_spell.c,v 1.5 2003/09/26 15:47:50 n0body Exp $
//@{
/*----------------------------------------------------------------------------
@@ -48,104 +48,52 @@
#include "ccl.h"
/**
- Syntax :
-;; // Warning, Some names and specifications should be changed
-;; // Todo parameter coherency ? negative for dealing damage,
positive for healing ?
-;;
-;; ... : for list.
-;; {a, b, c} : choice between a, b, or c.
-;; name#n : name is of type number.
-;; #n : Number.
-;; #t : {true, false}
-;; #target : {'self, 'Unit, 'position}
-;; #f_inv : {unholyarmor, invisibility}
-;; #f_haste : {bloodlust, slow, haste, HP, mana,
HP_percent, mana_percent}
-;; #f_flag : {invisibility, bloodlust, unholyarmor, slow,
haste, flameshield,
-;; HP, mana, HP_percent, mana_percent
-;; #flagtype : {coward, organic, undead, canattack, building}
-;; <condition> : Same syntax as 'condition
-;;
-;; (define-spell "IdentName" // Ident name for call in unit
-;; 'Showname "ShowName" // Name show in the engine
-;; 'ManaCost #n // Mana to cast the spell
-;; 'range #n // Range of the spell (0)
-;; 'Target #target // Which target is allowed (None by
default)
-;; 'Action '({
-;; Blizzard ('fields #n 'shards #n 'damage #n),
-;; CircleOfPower "unit-goal",
-;; DeathAndDecay(fields #n shards #n damage #n),
-;; DeathCoil,
-;; FireBall (ttl #n damage #n),
-;; FlameShield (ttl #n),
-;; Haste (#f_haste #n ...),
-;; Healing (HP#n), // Healing (HP >0) or exorcism (HP < 0)
-;; HolyVision "unit-revealer",
-;; Invisibility (flag #f_inv value #n missile
"MissileType")
-;; Polymorph "unittype",
-;; RaiseDead "skeleton",
-;; Runes (ttl #n damage #n),
-;; Summon "UnitType",
-;; Whirlwind (ttl #n)
-;; } )
-;; 'sound-when-cast "SoundConfig"
-;; 'missile-when-cast "MissileType"
-;; 'condition '( {
-;; Enemypresence (#t range #n), //
enemy in range
-;; DurationEffect (#t flag #f_flag value #n), //
"f_flag" < #n
-;; Alliance #t, //
check the target is allied.
-;; UnitTypeflag (#t #flagtype), // Unit
is a "type"
-;; ...}
-;; )
-;; 'autocast '(
-;; range #n
-;; condition (<condition>)// Additional condition
-;; +++order () // which target choose.
-;; )
-*/
-
-/*
-** Todo:
-** Some warnings are displayed only to developers (debugging),
-** but should be useful for users who modofify or create ccl.
-** Replace DebugLevel0Fn by appropriated functions.
-*/
-
-/**
** pointer on function.
** @param id : last keyword recognized.
** @param list : list to be parsed. (just the args).
** @param spell : spelltype to modify.
+** FIXME: remove all this cruft
*/
-typedef void f_ccl_spell(const char *id, SCM list, SpellType *spell);
+typedef void f_ccl_spell(const char *id, SCM list, SpellType *spell);
// **************************************************************************
// Direct affectation for spell
// **************************************************************************
-/*
-** Parse the missile for spell.
-** list = "MissileType"
+/**
+** Parse the dependency of spell.
+** list = (upgrade "upgradename")
*/
-local void ccl_spell_missilewhencast(const char *id, SCM list, SpellType
*spell)
+local void ccl_spell_dependency(const char *id, SCM list, SpellType *spell)
{
- char *missilewhencastname = NULL;
- MissileType *missile = spell->Missile;
-
assert (id != NULL);
assert (spell != NULL);
- missilewhencastname = gh_scm2newstr(list, NULL);
- spell->Missile = MissileTypeByIdent(missilewhencastname);
- if (missile != NULL && spell->Missile != missile) {
- DebugLevel3Fn("Redefinition in spell-type '%s' : %s : '%s' -> '%s'\n"
- _C_ spell->IdentName _C_ id _C_ spell->Missile->Ident _C_
missilewhencastname);
- }
- if (spell->Missile == NULL) {
- DebugLevel0Fn("in spell-type '%s' : %s : '%s' %s\n"
- _C_ spell->Name _C_ id _C_ missilewhencastname _C_ "does not
exist");
+
+ char *dependencyName = NULL;
+ SCM value;
+ int dependencyId = -1;
+
+ value = gh_car(list);
+
+ if (!gh_eq_p(value, gh_symbol2scm("upgrade"))) {
+ return;
}
- free(missilewhencastname);
+ list = gh_cdr(list);
+ value = gh_car(list);
+
+ dependencyName = gh_scm2newstr(value, NULL);
+ dependencyId = UpgradeIdByIdent(dependencyName);
+ if (dependencyId == -1)
+ {// warn user
+ DebugLevel0Fn("Bad upgrade-name '%s'\n" _C_ dependencyName);
+ free(dependencyName);
+ return ;
+ }
+ spell->DependencyId = dependencyId;
+ free(dependencyName);
}
+
// **************************************************************************
// Action parsers for spellAction
// **************************************************************************
@@ -154,51 +102,36 @@
** For blizzard and DeathAndDecay.
** list = fields #n shards #n damage #n
*/
-local char ccl_spell_action_blizzard(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionAreaBombardment(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
- int fields;
- int shards;
- int damage;
SCM value;
assert(SpellName);
assert(spellaction != NULL);
- fields = 0;
- shards = 0;
- damage = 0;
+ memset(spellaction,sizeof(spellaction),0);
for (; !gh_null_p(list); list = gh_cdr(list)) {
value = gh_car(list);
list = gh_cdr(list);
- // Todo, Warn for redefinitions ???
if (gh_eq_p(value, gh_symbol2scm("fields"))) {
- fields = gh_scm2int(gh_car(list));
+ spellaction->AreaBombardment.Fields = gh_scm2int(gh_car(list));
continue;
- }
- if (gh_eq_p(value, gh_symbol2scm("shards"))) {
- shards = gh_scm2int(gh_car(list));
+ } else if (gh_eq_p(value, gh_symbol2scm("shards"))) {
+ spellaction->AreaBombardment.Shards = gh_scm2int(gh_car(list));
continue;
- }
- if (gh_eq_p(value, gh_symbol2scm("damage"))) {
- damage = gh_scm2int(gh_car(list));
+ } else if (gh_eq_p(value, gh_symbol2scm("damage"))) {
+ spellaction->AreaBombardment.Damage = gh_scm2int(gh_car(list));
+ continue;
+ } else if (gh_eq_p(value, gh_symbol2scm("start-offset-x"))) {
+ spellaction->AreaBombardment.StartOffsetX =
gh_scm2int(gh_car(list));
+ continue;
+ } else if (gh_eq_p(value, gh_symbol2scm("start-offset-y"))) {
+ spellaction->AreaBombardment.StartOffsetY =
gh_scm2int(gh_car(list));
continue;
}
// warning user : unknow tag
DebugLevel0Fn("FIXME : better WARNING : unknow tag");
}
- if (damage == 0) {
- DebugLevel0Fn("in spell-type %s : %s" _C_ SpellName _C_
- "damage == 0 have no sense : Positive to deal damage, negative
for healing.");
- return 0;
- }
- if (fields <= 0 || shards <= 0) {
- DebugLevel0Fn("in spell-type %s : %s" _C_ SpellName _C_
- "fields <= 0 or shards <= 0 have no sense");
- return 0;
- }
- spellaction->Blizzard.Fields = fields;
- spellaction->Blizzard.Shards = shards;
- spellaction->Blizzard.Damage = damage;
return 1;
}
@@ -206,7 +139,7 @@
** For fireball and Runes.
** list = 'ttl #n 'damage #n
*/
-local char ccl_spell_action_fireball(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionFireball(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
int ttl;
int damage;
@@ -252,7 +185,7 @@
** For flameshield and whirlwind.
** list = 'ttl #n
*/
-local char ccl_spell_action_flameshield(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionFlameShield(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
int ttl;
SCM value;
@@ -288,7 +221,7 @@
** One or more.
** @todo Free when an error occurs. Do a function to do this.
*/
-local char ccl_spell_action_haste(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionHaste(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
struct {
const char *id;
@@ -355,7 +288,7 @@
** HP positive for healing, negative for dealing damage.
** list = (HP #n)
*/
-local char ccl_spell_action_healing(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionHealing(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
@@ -392,7 +325,7 @@
** For invisibility and unholyarmor.
** list = flag #f_inv value #n missile "missile-name"
*/
-local char ccl_spell_action_invisibility(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionInvisibility(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
const struct {
const char *id;
@@ -476,22 +409,19 @@
** list = ("unittypename")
** @note WARNING, use for other functions than summon, see
ccl_spell_action.
*/
-local char ccl_spell_action_summon(const char *SpellName, SCM list,
SpellActionType *spellaction)
+local char CclSpellParseActionSummon(const char *SpellName, SCM list,
SpellActionType *spellaction)
{
-
-
char *str;
UnitType *unittype;
- assert(SpellName);
+ assert(SpellName);
assert(spellaction != NULL);
str = gh_scm2newstr(list, NULL);
unittype = UnitTypeByIdent(str);
- spellaction->summon.unittype = unittype;
+ spellaction->Summon.UnitType = unittype;
if (unittype == NULL) {
- DebugLevel0Fn("in spell-type %s : Unittype '%s'doesn't exist" _C_
- SpellName _C_ str);
+ DebugLevel0Fn("in spell-type %s : Unittype '%s'doesn't exist" _C_
SpellName _C_ str);
free(str);
return 0;
}
@@ -518,26 +448,25 @@
local void ccl_spell_action(const char *id, SCM list, SpellType *spell)
{
int i;
- static struct {
- f_spell *fspell;
+ struct {
+ SpellFunc *fspell;
const char *id;
f_ccl_action *f;
} parser[] = {
- {CastBlizzard, "Blizzard", ccl_spell_action_blizzard},
- {CastCircleOfPower, "CircleOfPower",
ccl_spell_action_summon/*circleofpower*/},
- {CastBlizzard, "DeathAndDecay",
ccl_spell_action_blizzard/*deathanddecay*/},
- {CastDeathCoil, "DeathCoil", NULL},
- {CastFireball, "FireBall", ccl_spell_action_fireball},
- {CastFlameShield, "FlameShield", ccl_spell_action_flameshield},
- {CastHaste, "Haste", ccl_spell_action_haste},
- {CastHealing, "Healing", ccl_spell_action_healing},
- {CastHolyVision, "HolyVision", ccl_spell_action_summon/*holyvision*/},
- {CastInvisibility, "Invisibility", ccl_spell_action_invisibility},
- {CastPolymorph, "Polymorph", ccl_spell_action_summon/*polymorph*/},
- {CastRaiseDead, "RaiseDead", ccl_spell_action_summon/*raisedead*/},
- {CastRunes, "Runes", ccl_spell_action_fireball/*runes*/},
- {CastSummon, "Summon", ccl_spell_action_summon},
- {CastWhirlwind, "Whirlwind", ccl_spell_action_flameshield/*whirlwind*/},
+ {CastAreaBombardment, "area-bombardment",
CclSpellParseActionAreaBombardment},
+ {CastSpawnPortal, "spawn-portal",
CclSpellParseActionSummon/*circleofpower*/},
+ {CastDeathCoil, "death-coil", NULL},
+ {CastFireball, "fireball", CclSpellParseActionFireball},
+ {CastFlameShield, "flame-shield", CclSpellParseActionFlameShield},
+ {CastHaste, "haste", CclSpellParseActionHaste},
+ {CastHealing, "healing", CclSpellParseActionHealing},
+ {CastHolyVision, "HolyVision", CclSpellParseActionSummon/*holyvision*/},
+ {CastInvisibility, "Invisibility", CclSpellParseActionInvisibility},
+ {CastPolymorph, "Polymorph", CclSpellParseActionSummon/*polymorph*/},
+ {CastRaiseDead, "RaiseDead", CclSpellParseActionSummon/*raisedead*/},
+ {CastRunes, "Runes", CclSpellParseActionFireball/*runes*/},
+ {CastSummon, "Summon", CclSpellParseActionSummon},
+ {CastWhirlwind, "Whirlwind",
CclSpellParseActionFlameShield/*whirlwind*/},
{0, NULL, NULL}
};
@@ -942,6 +871,7 @@
local SCM CclDefineSpell(SCM list)
{
char *identname;
+ char *str;
SpellType *spell;
SCM value;
@@ -957,6 +887,7 @@
memset(spell,0,sizeof(SpellType));
spell->Ident=SpellTypeCount-1;
spell->IdentName=identname;
+ spell->DependencyId = -1;
}
while (!gh_null_p(list)) {
value = gh_car(list);
@@ -1008,9 +939,19 @@
}
list=gh_cdr(list);
} else if (gh_eq_p(value,gh_symbol2scm("missile-when-cast"))) {
- ccl_spell_missilewhencast("missile-when-cast",gh_car(list),spell);
+ str = gh_scm2newstr(gh_car(list), NULL);
+ spell->Missile = MissileTypeByIdent(str);
+ if (spell->Missile == NULL) {
+ DebugLevel0Fn("in spell-type '%s' : missile %s does not exist\n"
+ _C_ spell->Name _C_ str);
+ }
+ free(str);
list=gh_cdr(list);
- } else {
+ } else if (gh_eq_p(value,gh_symbol2scm("depend"))) {
+ ccl_spell_dependency("depend", gh_car(list), spell);
+ list = gh_cdr(list);
+ } else
+ {
errl("Unsupported tag", value);
}
}
@@ -1050,7 +991,7 @@
CLprintf(file," 'sound-when-cast
\"%s\"\n",spell->SoundWhenCast.Name);
}
if (spell->Missile) {
- CLprintf(file," 'missile-when-casted
\"%s\"\n",spell->Missile->Ident);
+ CLprintf(file," 'missile-when-cast
\"%s\"\n",spell->Missile->Ident);
}
//
// Target type.
@@ -1077,23 +1018,25 @@
// Save the action(effect of the spell)
//
CLprintf(file," 'action");
- if (spell->f==CastBlizzard) {
- CLprintf(file," '(Blizzard (fields %d shards %d damage %d) )\n",
- spell->SpellAction->Blizzard.Fields,
- spell->SpellAction->Blizzard.Shards,
- spell->SpellAction->Blizzard.Damage);
+ if (spell->f==CastAreaBombardment) {
+ CLprintf(file," '(area-bombardment (fields %d shards %d damage %d
start-offset-x %d start-offset-y %d) )\n",
+ spell->SpellAction->AreaBombardment.Fields,
+ spell->SpellAction->AreaBombardment.Shards,
+ spell->SpellAction->AreaBombardment.Damage,
+ spell->SpellAction->AreaBombardment.StartOffsetX,
+ spell->SpellAction->AreaBombardment.StartOffsetY);
} else if (spell->f==CastFireball) {
- CLprintf(file," '(FireBall (ttl %d damage %d) )\n",
+ CLprintf(file," '(fireball (ttl %d damage %d) )\n",
spell->SpellAction->Fireball.TTL,
spell->SpellAction->Fireball.Damage);
} else if (spell->f==CastHolyVision) {
CLprintf(file," '(HolyVision \"%s\"
)\n",spell->SpellAction->holyvision.revealer->Ident);
} else if (spell->f==CastHealing) {
- CLprintf(file," '(Healing (HP %d)
)\n",spell->SpellAction->healing.HP);
+ CLprintf(file," '(healing (HP %d)
)\n",spell->SpellAction->healing.HP);
} else if (spell->f==CastSummon) {
- CLprintf(file," '(Summon
\"%s\")\n",spell->SpellAction->summon.unittype->Ident);
+ CLprintf(file," '(Summon
\"%s\")\n",spell->SpellAction->Summon.UnitType->Ident);
} else if (spell->f==CastHaste) {
- CLprintf(file," '(Haste ( ");
+ CLprintf(file," '(haste ( ");
hinfo=&spell->SpellAction->haste;
while (hinfo) {
switch (hinfo->flag) {
@@ -1141,22 +1084,22 @@
spell->SpellAction->invisibility.missile->Ident);
} else if (spell->f==CastPolymorph) {
CLprintf(file," '(Polymorph \"%s\")\n",
- spell->SpellAction->polymorph.unit->Ident);
+ spell->SpellAction->Polymorph.NewForm->Ident);
} else if (spell->f==CastRaiseDead) {
CLprintf(file," '(RaiseDead \"%s\")\n",
- spell->SpellAction->raisedead.skeleton->Ident);
+ spell->SpellAction->RaiseDead.Skeleton->Ident);
} else if (spell->f==CastFlameShield) {
- CLprintf(file," '(FlameShield (ttl %d) )\n",
+ CLprintf(file," '(flame-shield (ttl %d) )\n",
spell->SpellAction->FlameShield.TTL);
} else if (spell->f==CastRunes) {
CLprintf(file," '(Runes (ttl %d damage %d) )\n",
spell->SpellAction->runes.TTL,
- spell->SpellAction->runes.damage);
- } else if (spell->f==CastCircleOfPower) {
- CLprintf(file," '(CircleOfPower \"%s\")\n",
+ spell->SpellAction->runes.Damage);
+ } else if (spell->f==CastSpawnPortal) {
+ CLprintf(file," '(spawn-portal \"%s\")\n",
spell->SpellAction->SpawnPortal.PortalType->Ident);
} else if (spell->f==CastDeathCoil) {
- CLprintf(file," '(DeathCoil)\n");
+ CLprintf(file," '(death-coil)\n");
// FIXME: more?
} else if (spell->f==CastWhirlwind) {
CLprintf(file," '(Whirlwind (ttl %d) )\n",
Index: stratagus/src/clone/spells.c
diff -u stratagus/src/clone/spells.c:1.99 stratagus/src/clone/spells.c:1.100
--- stratagus/src/clone/spells.c:1.99 Fri Sep 26 05:15:22 2003
+++ stratagus/src/clone/spells.c Fri Sep 26 11:47:50 2003
@@ -27,7 +27,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.c,v 1.99 2003/09/26 09:15:22 mr-russ Exp $
+// $Id: spells.c,v 1.100 2003/09/26 15:47:50 n0body Exp $
/*
** And when we cast our final spell
@@ -80,7 +80,7 @@
/// How many spell-types are available
-global int SpellTypeCount = 0; // Usefull ?
+global int SpellTypeCount = 0;
/*----------------------------------------------------------------------------
-- Functions (Spells Controllers/Callbacks)
@@ -120,28 +120,25 @@
// explosions are on each tile on the way
// approx
- if (missile->TTL <= missile->State && missile->TTL % 2 == 0)
- {
+ 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;
+ x = missile->X + TileSizeX / 2;
+ y = missile->Y + TileSizeY / 2;
- MakeMissile(MissileTypeExplosion, x, y, x, y);
+ MakeMissile(MissileTypeExplosion, x, y, x, y);
- x = x / TileSizeX;
- y = y / TileSizeY;
+ 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
- }
- }
+ 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
+ }
+ }
}
}
@@ -154,134 +151,108 @@
*/
local void SpellDeathCoilController(Missile * missile)
{
- Unit *table[UnitMax];
- int i;
- int n;
- Unit *source;
+ 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++;
- }
+ 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;
+ source->XP += missile->TargetUnit->HP;
#else
- source->XP += missile->TargetUnit->Type->Points;
+ source->XP += missile->TargetUnit->Type->Points;
#endif
- ++source->Kills;
- missile->TargetUnit->HP = 0;
- LetUnitDie(missile->TargetUnit);
- }
- else
- {
+ ++source->Kills;
+ missile->TargetUnit->HP = 0;
+ LetUnitDie(missile->TargetUnit);
+ } else {
#ifdef USE_HP_FOR_XP
- source->XP += 50;
+ 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;
- }
- }
+ missile->TargetUnit->HP -= 50;
}
- else
- //
- // No target unit -- try enemies in range 5x5 // Must be parametrable
- //
- {
- int ec = 0; // enemy count
- int x = missile->DX / TileSizeX;
- int 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++;
- }
+ 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 = 0; // enemy count
+ int x = missile->DX / TileSizeX;
+ int 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;
+ source->XP += table[i]->HP;
#else
- source->XP +=
table[i]->Type->Points;
+ source->XP += table[i]->Type->Points;
#endif
- ++source->Kills;
- table[i]->HP = 0;
- LetUnitDie(table[i]); // too
much damage
- }
- else
- {
+ ++source->Kills;
+ table[i]->HP = 0;
+ LetUnitDie(table[i]); // too much damage
+ } else {
#ifdef USE_HP_FOR_XP
- source->XP += 50/ec;
+ 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;
- }
- }
+ 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;
}
+ }
}
+ }
}
/**
@@ -307,32 +278,26 @@
//
// 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 ?
- }
- }
+ 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)))
- {
+ 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
- }
- }
+ 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 );
@@ -340,7 +305,7 @@
//
// Changes direction every 3 seconds (approx.)
//
- if (!(missile->TTL % 100)) { // missile has reached target unit/spot
+ if (!(missile->TTL % 100)) { // missile has reached target unit/spot
int nx, ny;
do {
@@ -375,23 +340,19 @@
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
- }
+ 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);
+ if (missile->TTL % 100 == 0) {
+ MakeMissile(MissileTypeRune, missile->X, missile->Y,missile->X,
missile->Y);
}
}
@@ -409,8 +370,7 @@
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
- };
+ 20, -20, 24, -15, 27, -10, 30, -5, 31, 0, 32};
Unit *table[UnitMax];
int n;
int i;
@@ -434,33 +394,28 @@
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->TargetUnit->Orders[0].Action == UnitActionDie) {
+ missile->TTL = i;
}
- if (missile->TTL == 0)
- {
- missile->TargetUnit->FlameShield = 0;
+ 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;
+ 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);
- }
+ 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);
+ }
}
}
@@ -472,82 +427,6 @@
// Cast the Spell
// ****************************************************************************
-// Blizzard
-// NOTE: vladi: blizzard differs than original in this way:
-// original: launches 50 shards at 5 random spots x 10 for 25 mana.
-
-/**
-** Cast blizzard.
-**
-** @param caster Unit that casts the spell
-** @param spell Spell-type pointer
-** @param target Target unit that spell is addressed to
-** @param x X coord of target spot when/if target does not exist
-** @param y Y coord of target spot when/if target does not exist
-**
-** @return =!0 if spell should be repeated, 0 if not
-*/
-global int CastBlizzard(Unit* caster, const SpellType* spell,
- Unit* target __attribute__((unused)), int x, int y)
-{
- int fields;
- int shards;
- int damage;
- Missile *mis = NULL;
- int sx;
- int sy;
- int dx;
- int dy;
- int i;
-
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- //assert(x in range, y in range);
-
- fields = spell->SpellAction->Blizzard.Fields;
- shards = spell->SpellAction->Blizzard.Shards;
- damage = spell->SpellAction->Blizzard.Damage;
- while (fields--)
- {
- // FIXME : radius configurable...
- do {
- // find new destination in the map
- dx = x + SyncRand() % 5 - 2;
- dy = y + SyncRand() % 5 - 2;
- } while (dx < 0 && dy < 0 && dx >= TheMap.Width && dy >=
TheMap.Height);
- sx = dx - 4;
- sy = dy - 4;
- for (i = 0; i < shards; ++i)
- {
- mis = MakeMissile(spell->Missile,
- sx * TileSizeX +
TileSizeX / 2,
- sy * TileSizeY +
TileSizeY / 2,
- dx * TileSizeX +
TileSizeX / 2,
- dy * TileSizeY +
TileSizeY / 2);
- if (mis->Type->Speed)
- {
- mis->Delay = i * mis->Type->Sleep * 2 * TileSizeX /
mis->Type->Speed;
- }
- else
- {
- DebugLevel0Fn("Missile-type '%s' must have
speed non null" _C_ spell->Missile->Ident);
- // Or assert();
- // warning : bad conf.
- }
- mis->Damage = damage;
- // FIXME: not correct -- blizzard should continue even if
mage is
- // destroyed (though it will be quite short time...)
- mis->SourceUnit = caster;
- RefsDebugCheck(!caster->Refs || caster->Destroyed);
- caster->Refs++;
- }
- }
- PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
- caster->Mana -= spell->ManaCost;
- return caster->Mana > spell->ManaCost;
-}
-
/**
** Cast circle of power.
**
@@ -559,43 +438,45 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastCircleOfPower(Unit* caster, const SpellType* spell
__attribute__((unused)),
+global int CastSpawnPortal(Unit* caster, const SpellType* spell
__attribute__((unused)),
Unit* target __attribute__((unused)), int x, int y)
{
// FIXME: vladi: cop should be placed only on explored land
- Unit *cop = NULL;
- UnitType *ucop = spell->SpellAction->SpawnPortal.PortalType;
-
+ Unit *portal;
+ UnitType *ptype;
+
assert(caster);
assert(spell);
assert(spell->SpellAction);
assert(spell->SpellAction->SpawnPortal.PortalType);
-// assert(x in range, y in range);
- cop = caster->Goal;
- if (cop)
- {
- // FIXME: if cop is already defined --> move it, but it doesn't
work?
- RemoveUnit(cop, NULL);
- PlaceUnit(cop, x, y);
- }
- else
- {
- cop = MakeUnitAndPlace(x, y, ucop, &Players[PlayerMax - 1]);
+ ptype = spell->SpellAction->SpawnPortal.PortalType;
+
+ portal = caster->Goal;
+ if (portal) {
+ // FIXME: if cop is already defined --> move it, but it doesn't work?
+ RemoveUnit(portal, NULL);
+ PlaceUnit(portal, x, y);
+ } else {
+ portal = MakeUnitAndPlace(x, y, ptype, &Players[PlayerMax - 1]);
}
- MakeMissile(spell->Missile,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
- // Next is used to link to destination circle of power
- caster->Goal = cop;
- RefsDebugCheck(!cop->Refs || cop->Destroyed);
- cop->Refs++;
+ MakeMissile(spell->Missile,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
+ // Goal is used to link to destination circle of power
+ caster->Goal = portal;
+ RefsDebugCheck(!portal->Refs || portal->Destroyed);
+ portal->Refs++;
//FIXME: setting destination circle of power should use mana
return 0;
}
+// AreaBombardment
+// NOTE: vladi: blizzard differs than original in this way:
+// original: launches 50 shards at 5 random spots x 10 for 25 mana.
+
/**
-** Cast death and decay.
+** Cast blizzard.
**
** @param caster Unit that casts the spell
** @param spell Spell-type pointer
@@ -604,53 +485,61 @@
** @param y Y coord of target spot when/if target does not exist
**
** @return =!0 if spell should be repeated, 0 if not
-** @todo unify DeathAndDecay and blizzard function. (if possible)
*/
-global int CastDeathAndDecay(Unit* caster, const SpellType* spell,
+global int CastAreaBombardment(Unit* caster, const SpellType* spell,
Unit* target __attribute__((unused)), int x, int y)
{
- int fields; // blizzard thing, yep :)
+ int fields;
int shards;
- int damage;
+ int damage;
Missile *mis = NULL;
+ int offsetx;
+ int offsety;
int dx;
int dy;
int i;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
-// assert(x in range, y in range);
-
- fields = spell->SpellAction->DeathAndDecay.Fields;
- shards = spell->SpellAction->DeathAndDecay.Shards;
- damage = spell->SpellAction->DeathAndDecay.Damage;
- while (fields--)
- {
- do {
- // find new destination in the map
- dx = x + SyncRand() % 5 - 2;
- dy = y + SyncRand() % 5 - 2;
- } while (dx < 0 && dy < 0 && dx >= TheMap.Width && dy >=
TheMap.Height);
- for (i = 0; i < shards; ++i)
- {
- mis = MakeMissile(spell->Missile,
- dx * TileSizeX + TileSizeX / 2, dy * TileSizeY +
TileSizeY / 2,
- dx * TileSizeX + TileSizeX / 2, dy * TileSizeY +
TileSizeY / 2);
- mis->Damage = damage;
- //FIXME: not correct -- death and decay should continue
even if
- // death knight is destroyed (though it will be quite
- // short time...)
- mis->Delay = i * mis->Type->Sleep
- * VideoGraphicFrames(mis->Type->Sprite);
- mis->SourceUnit = caster;
- RefsDebugCheck(!caster->Refs || caster->Destroyed);
- caster->Refs++;
- }
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ //assert(x in range, y in range);
+
+ fields = spell->SpellAction->AreaBombardment.Fields;
+ shards = spell->SpellAction->AreaBombardment.Shards;
+ damage = spell->SpellAction->AreaBombardment.Damage;
+ offsetx = spell->SpellAction->AreaBombardment.StartOffsetX;
+ offsety = spell->SpellAction->AreaBombardment.StartOffsetY;
+ while (fields--) {
+ // FIXME : radius configurable...
+ do {
+ // find new destination in the map
+ dx = x + SyncRand() % 5 - 2;
+ dy = y + SyncRand() % 5 - 2;
+ } while (dx < 0 && dy < 0 && dx >= TheMap.Width && dy >= TheMap.Height);
+ for (i = 0; i < shards; ++i) {
+ mis = MakeMissile(spell->Missile,
+ dx * TileSizeX + TileSizeX / 2 + offsetx,
+ dy * TileSizeY + TileSizeY / 2 + offsety,
+ dx * TileSizeX + TileSizeX / 2,
+ dy * TileSizeY + TileSizeY / 2);
+ // 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) {
+ mis->Delay = i * mis->Type->Sleep * 2 * TileSizeX /
mis->Type->Speed;
+ } else {
+ mis->Delay = i * mis->Type->Sleep *
VideoGraphicFrames(mis->Type->Sprite);
+ }
+ mis->Damage = damage;
+ // FIXME: not correct -- blizzard should continue even if mage is
+ // destroyed (though it will be quite short time...)
+ mis->SourceUnit = caster;
+ RefsDebugCheck(!caster->Refs || caster->Destroyed);
+ caster->Refs++;
}
+ }
PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
caster->Mana -= spell->ManaCost;
- return (caster->Mana > spell->ManaCost);
+ return caster->Mana > spell->ManaCost;
}
/**
@@ -664,8 +553,7 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastDeathCoil(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastDeathCoil(Unit* caster, const SpellType* spell, Unit*
target,int x, int y)
{
Missile *mis = NULL;
int sx = caster->X;
@@ -674,20 +562,19 @@
assert(caster);
assert(spell);
assert(spell->SpellAction);
-// assert(target);
-// assert(x in range, y in range);
+// assert(target);
+// assert(x in range, y in range);
caster->Mana -= spell->ManaCost;
PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
mis = MakeMissile(spell->Missile,
- sx * TileSizeX + TileSizeX / 2, sy * TileSizeY + TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
+ sx * TileSizeX + TileSizeX / 2, sy * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
mis->SourceUnit = caster;
RefsDebugCheck(!caster->Refs || caster->Destroyed);
caster->Refs++;
- if (target)
- {
+ if (target) {
mis->TargetUnit = target;
RefsDebugCheck(!target->Refs || target->Destroyed);
target->Refs++;
@@ -715,18 +602,16 @@
int sy;
int dist;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
-// assert(target);
-// assert(x in range, y in range);
- assert(spell->Missile);
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(spell->Missile);
// NOTE: fireball can be casted on spot
sx = caster->X;
sy = caster->Y;
dist = MapDistance(sx, sy, x, y);
- assert(dist != 0);
+ assert(dist != 0);
x += ((x - sx) * 10) / dist;
y += ((y - sy) * 10) / dist;
sx = sx * TileSizeX + TileSizeX / 2;
@@ -759,29 +644,28 @@
global int CastFlameShield(Unit* caster, const SpellType* spell, Unit* target,
int x __attribute__((unused)), int y __attribute__((unused)))
{
- Missile* mis = NULL;
- int i;
+ Missile* mis = NULL;
+ int i;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(target);
-// assert(x in range, y in range);
- assert(spell->Missile);
-
- // get mana cost
- caster->Mana -= spell->ManaCost;
- target->FlameShield = spell->SpellAction->FlameShield.TTL;
- PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
- for (i = 0; i < 5; i++)
- {
- mis = MakeMissile(spell->Missile, 0, 0, 0, 0);
- mis->TTL = spell->SpellAction->FlameShield.TTL + i * 7;
- mis->TargetUnit = target;
- mis->Controller = SpellFlameShieldController;
- RefsDebugCheck(!target->Refs || target->Destroyed);
- target->Refs++;
- }
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(target);
+// assert(x in range, y in range);
+ assert(spell->Missile);
+
+ // get mana cost
+ caster->Mana -= spell->ManaCost;
+ target->FlameShield = spell->SpellAction->FlameShield.TTL;
+ PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
+ for (i = 0; i < 5; i++) {
+ mis = MakeMissile(spell->Missile, 0, 0, 0, 0);
+ mis->TTL = spell->SpellAction->FlameShield.TTL + i * 7;
+ mis->TargetUnit = target;
+ mis->Controller = SpellFlameShieldController;
+ RefsDebugCheck(!target->Refs || target->Destroyed);
+ target->Refs++;
+ }
return 0;
}
@@ -799,93 +683,69 @@
global int CastHaste(Unit* caster, const SpellType* spell, Unit* target,
int x, int y)
{
- struct s_haste *haste;
+ struct s_haste *haste;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(target);
-
- // get mana cost
- caster->Mana -= spell->ManaCost;
-
- for (haste = &spell->SpellAction->haste; haste != NULL; haste =
haste->next)
- {
- // FIXME modify unit (slow, bloodlust, ..) -> flag[] ?
- switch (haste->flag)
- {
- case flag_slow:
- {
- target->Slow = haste->value / CYCLES_PER_SECOND;
- break;
- }
- case flag_haste:
- {
- target->Haste = haste->value /
CYCLES_PER_SECOND;
- break;
- }
- case flag_bloodlust:
- {
- target->Bloodlust = haste->value /
CYCLES_PER_SECOND;
- break;
- }
- case flag_HP:
- {
- target->HP = haste->value;
- if (target->HP <= 0)
- {
- target->HP = 1; // could be to 0 ??
- }
- if (target->Stats->HitPoints < target->HP)
- {
- target->HP = target->Stats->HitPoints;
- }
- break;
- }
- case flag_Mana:
- {
- target->Mana = haste->value;
- if (target->Type->_MaxMana < target->Mana)
- {
- target->Mana = target->Type->_MaxMana;
- }
- break;
- }
- case flag_HP_percent:
- {
- target->HP = target->HP * haste->value / 100;
- if (target->HP < 0)
- {
- target->HP = 1; // could be to 0 ??
- }
- if (target->Stats->HitPoints < target->HP)
- {
- target->HP = target->Stats->HitPoints;
- }
- break;
- }
- case flag_Mana_percent:
- {
- target->Mana = target->Mana * haste->value /
100;
- if (target->Type->_MaxMana < target->Mana)
- {
- target->Mana = target->Type->_MaxMana;
- }
- break;
- }
- default:
- {
- // Warn devellopers
- assert(0);
- }
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(target);
+
+ // get mana cost
+ caster->Mana -= spell->ManaCost;
+
+ for (haste = &spell->SpellAction->haste; haste != NULL; haste =
haste->next) {
+ // FIXME modify unit (slow, bloodlust, ..) -> flag[] ?
+ switch (haste->flag) {
+ case flag_slow:
+ target->Slow = haste->value / CYCLES_PER_SECOND;
+ break;
+ case flag_haste:
+ target->Haste = haste->value / CYCLES_PER_SECOND;
+ break;
+ case flag_bloodlust:
+ target->Bloodlust = haste->value / CYCLES_PER_SECOND;
+ break;
+ case flag_HP:
+ target->HP = haste->value;
+ if (target->HP <= 0) {
+ target->HP = 1; // could be to 0 ??
+ }
+ if (target->Stats->HitPoints < target->HP) {
+ target->HP = target->Stats->HitPoints;
}
+ break;
+ case flag_Mana:
+ target->Mana = haste->value;
+ if (target->Type->_MaxMana < target->Mana) {// What is Maxmana
per unit.
+ target->Mana = target->Type->_MaxMana;
+ }
+ break;
+ case flag_HP_percent:
+ target->HP = target->HP * haste->value / 100;
+ if (target->HP < 0) {
+ target->HP = 1; // could be to 0 ??
+ }
+ if (target->Stats->HitPoints < target->HP) {
+ target->HP = target->Stats->HitPoints;
+ }
+ break;
+ case flag_Mana_percent:
+ target->Mana = target->Mana * haste->value / 100;
+ if (target->Type->_MaxMana < target->Mana) {// What is Maxmana
per unit.
+ target->Mana = target->Type->_MaxMana;
+ }
+ break;
+ default:
+ // Warn devellopers
+ assert(0);
}
- CheckUnitToBeDrawn(target);
- PlayGameSound(spell->SoundWhenCast.Sound,MaxSampleVolume);
- MakeMissile(spell->Missile,
- x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2,
- x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2 );
- return 0;
+ }
+ CheckUnitToBeDrawn(target);
+ PlayGameSound(spell->SoundWhenCast.Sound,MaxSampleVolume);
+ MakeMissile(spell->Missile,
+ x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2,
+ x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2 );
+ return 0;
}
/**
@@ -899,54 +759,49 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastHealing(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastHealing(Unit* caster, const SpellType* spell, Unit* target,int
x, int y)
{
- int i;
- int diffHP;
- int diffMana = caster->Mana;
- int HP = spell->SpellAction->healing.HP;
- int Mana = spell->ManaCost;
-
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(target);
-
- // Healing or exorcism
- diffHP = (HP > 0) ? target->Stats->HitPoints - target->HP : target->HP;
- i = min(diffHP / HP + (diffHP % HP ? 1 : 0),
- diffMana / Mana + (diffMana % Mana ? 1 : 0));
- // Stop when no mana or full HP
+ int i;
+ int diffHP;
+ int diffMana = caster->Mana;
+ int HP = spell->SpellAction->healing.HP;
+ int Mana = spell->ManaCost;
+
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(target);
+
+ // Healing or exorcism
+ diffHP = (HP > 0) ? target->Stats->HitPoints - target->HP : target->HP;
+ i = min(diffHP / HP + (diffHP % HP ? 1 : 0),
+ diffMana / Mana + (diffMana % Mana ? 1 : 0));
+ // Stop when no mana or full HP
caster->Mana -= i * Mana;
target->HP += i * HP;
- if (HP < 0)
- {
+
+ if (HP < 0) {
#ifdef USE_HP_FOR_XP
- caster->XP += i * HP;
+ caster->XP += i * HP;
#endif
- if (!target->HP)
- {
- caster->Player->Score += target->Type->Points;
- if (target->Type->Building)
- {
- caster->Player->TotalRazings++;
- }
- else
- {
- caster->Player->TotalKills++;
- }
+ if (!target->HP) {
+ caster->Player->Score += target->Type->Points;
+ if (target->Type->Building) {
+ caster->Player->TotalRazings++;
+ } else {
+ caster->Player->TotalKills++;
+ }
#ifndef USE_HP_FOR_XP
- caster->XP += target->Type->Points;
+ caster->XP += target->Type->Points;
#endif
- caster->Kills++;
- LetUnitDie(target);
- }
+ caster->Kills++;
+ LetUnitDie(target);
}
- PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
- MakeMissile(spell->Missile,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY +
TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY +
TileSizeY / 2);
+ }
+ PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
+ MakeMissile(spell->Missile,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
return 0;
}
@@ -961,16 +816,15 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastHolyVision(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastHolyVision(Unit* caster, const SpellType* spell, Unit*
target,int x, int y)
{
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
-// assert(x in range, y in range);
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+// assert(x in range, y in range);
caster->Mana -= spell->ManaCost; // get mana cost
- // FIXME Do a fonction to reveal map (use for attack revealer) instead of
create unit
+ // FIXME: compact with summon.
target = MakeUnit(spell->SpellAction->holyvision.revealer, caster->Player);
target->Orders[0].Action = UnitActionStill;
target->HP = 0;
@@ -997,53 +851,44 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastInvisibility(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastInvisibility(Unit* caster, const SpellType* spell, Unit*
target,int x, int y)
{
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(target);
- assert(spell->SpellAction->invisibility.missile);
-
- // get mana cost
- caster->Mana -= spell->ManaCost;
- if (target->Type->Volatile)
- {
- RemoveUnit(target,NULL);
- UnitLost(target);
- UnitClearOrders(target);
- ReleaseUnit(target);
- MakeMissile(spell->SpellAction->invisibility.missile,
- x * TileSizeX + TileSizeX / 2, y *
TileSizeY + TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y *
TileSizeY + TileSizeY / 2);
- }
- else
- {
- switch (spell->SpellAction->invisibility.flag)
- {
- case flag_invisibility:
- {
- target->Invisible =
spell->SpellAction->invisibility.value;
- target->Invisible /= CYCLES_PER_SECOND;
- }
- case flag_unholyarmor:
- {
- target->UnholyArmor =
spell->SpellAction->invisibility.value;
- target->UnholyArmor /= CYCLES_PER_SECOND;
- }
- default:
- {
- assert(0);
- // Warn devellopers
- }
- }
- CheckUnitToBeDrawn(target);
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(target);
+ assert(spell->SpellAction->invisibility.missile);
+
+ // get mana cost
+ caster->Mana -= spell->ManaCost;
+ if (target->Type->Volatile) {
+ RemoveUnit(target,NULL);
+ UnitLost(target);
+ UnitClearOrders(target);
+ ReleaseUnit(target);
+ MakeMissile(spell->SpellAction->invisibility.missile,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
+ } else {
+ switch (spell->SpellAction->invisibility.flag) {
+ case flag_invisibility:
+ target->Invisible = spell->SpellAction->invisibility.value;
+ target->Invisible /= CYCLES_PER_SECOND;
+ break;
+ case flag_unholyarmor:
+ target->UnholyArmor = spell->SpellAction->invisibility.value;
+ target->UnholyArmor /= CYCLES_PER_SECOND;
+ break;
+ default:
+ // Something is WRONG!!!
+ assert(0);
}
- PlayGameSound(spell->SoundWhenCast.Sound,MaxSampleVolume);
- MakeMissile(spell->Missile,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY +
TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY +
TileSizeY / 2 );
+ CheckUnitToBeDrawn(target);
+ }
+ PlayGameSound(spell->SoundWhenCast.Sound,MaxSampleVolume);
+ MakeMissile(spell->Missile,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2 );
return 0;
}
@@ -1058,47 +903,42 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastPolymorph(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastPolymorph(Unit* caster, const SpellType* spell, Unit*
target,int x, int y)
{
- UnitType* type = spell->SpellAction->polymorph.unit;
+ UnitType* type = spell->SpellAction->Polymorph.NewForm;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(target);
- assert(spell->SpellAction->polymorph.unit);
-
- caster->Player->Score += target->Type->Points;
- if (target->Type->Building)
- {
- caster->Player->TotalRazings++;
- }
- else
- {
- caster->Player->TotalKills++;
- }
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(target);
+ assert(type);
+
+ caster->Player->Score += target->Type->Points;
+ if (target->Type->Building) {
+ caster->Player->TotalRazings++;
+ } else {
+ caster->Player->TotalKills++;
+ }
#ifdef USE_HP_FOR_XP
- caster->XP += target->HP;
+ caster->XP += target->HP;
#else
- caster->XP += target->Type->Points;
+ caster->XP += target->Type->Points;
#endif
- caster->Kills++;
- // as said somewhere else -- no corpses :)
- RemoveUnit(target,NULL);
- UnitLost(target);
- UnitClearOrders(target);
- ReleaseUnit(target);
- if (UnitTypeCanMoveTo(x, y, type))
- {
- MakeUnitAndPlace(x, y, type, Players + PlayerNumNeutral);
- }
- caster->Mana -= spell->ManaCost;
- PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
- MakeMissile(spell->Missile,
+ caster->Kills++;
+ // as said somewhere else -- no corpses :)
+ RemoveUnit(target,NULL);
+ UnitLost(target);
+ UnitClearOrders(target);
+ ReleaseUnit(target);
+ if (UnitTypeCanMoveTo(x, y, type)) {
+ MakeUnitAndPlace(x, y, type, Players + PlayerNumNeutral);
+ }
+ caster->Mana -= spell->ManaCost;
+ PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
+ MakeMissile(spell->Missile,
x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2,
x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2 );
- return 0;
+ return 0;
}
/**
@@ -1112,47 +952,49 @@
**
** @return =!0 if spell should be repeated, 0 if not
*/
-global int CastRaiseDead(Unit* caster, const SpellType* spell, Unit* target,
- int x, int y)
+global int CastRaiseDead(Unit* caster, const SpellType* spell, Unit*
target,int x, int y)
{
Unit **corpses;
Unit *tempcorpse;
UnitType *skeleton;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(spell->SpellAction->raisedead.skeleton != NULL);
-// assert(x in range, y in range);
- skeleton = spell->SpellAction->raisedead.skeleton;
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+// assert(x in range, y in range);
+ skeleton = spell->SpellAction->RaiseDead.Skeleton;
+ assert(skeleton);
corpses = &CorpseList;
- while (caster->Mana >= spell->ManaCost && *corpses)
- {
+ while (*corpses) {
// FIXME: this tries to raise all corps, ohje
// FIXME: I can raise ships?
- if ((*corpses)->Orders[0].Action == UnitActionDie
- && !(*corpses)->Type->Building
- && (*corpses)->X >= x - 1 && (*corpses)->X <= x + 1
- && (*corpses)->Y >= y - 1 && (*corpses)->Y <= y + 1)
- {
- // FIXME: did they count on food?
- // Can there be more than 1 skeleton created on the same
tile? yes
- target = MakeUnit(skeleton, caster->Player);
- target->X = (*corpses)->X;
- target->Y = (*corpses)->Y;
- DropOutOnSide(target,LookingW,0,0);
- // set life span
- target->TTL = GameCycle + target->Type->DecayRate * 6 *
CYCLES_PER_SECOND;
- CheckUnitToBeDrawn(target);
- tempcorpse = *corpses;
- corpses = &(*corpses)->Next;
- ReleaseUnit(tempcorpse);
- caster->Mana -= spell->ManaCost;
- corpses = &(*corpses)->Next;
+ if ((*corpses)->Orders[0].Action == UnitActionDie
+ && !(*corpses)->Type->Building
+ && (*corpses)->X >= x - 1 && (*corpses)->X <= x + 1
+ && (*corpses)->Y >= y - 1 && (*corpses)->Y <= y + 1) {
+ // FIXME: did they count on food?
+ // nobody: unlikely.
+ // Can there be more than 1 skeleton created on the same tile? yes
+ target = MakeUnit(skeleton, caster->Player);
+ target->X = (*corpses)->X;
+ target->Y = (*corpses)->Y;
+ DropOutOnSide(target,LookingW,0,0);
+ // set life span
+ target->TTL = GameCycle + target->Type->DecayRate * 6 *
CYCLES_PER_SECOND;
+ CheckUnitToBeDrawn(target);
+ tempcorpse = *corpses;
+ corpses = &(*corpses)->Next;
+ ReleaseUnit(tempcorpse);
+ caster->Mana -= spell->ManaCost;
+ if (caster->Mana<spell->ManaCost) {
+ break;
}
+ } else {
+ corpses=&(*corpses)->Next;
}
+ }
PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
MakeMissile(spell->Missile,
x*TileSizeX+TileSizeX/2, y*TileSizeY+TileSizeY/2,
@@ -1172,44 +1014,43 @@
** @return =!0 if spell should be repeated, 0 if not
*/
global int CastRunes(Unit* caster, const SpellType* spell,
- Unit* target __attribute__((unused)), int x, int y)
+ Unit* target __attribute__((unused)), int x, int y)
{
Missile *mis = NULL;
- const int xx[] = {-1, +1, 0, 0, 0};
- const int yy[] = {0, 0, 0, -1, +1};
- int oldx = x;
- int oldy = y;
- int i;
-
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
-// assert(x in range, y in range);
+ const int xx[] = {-1,+1, 0, 0, 0};
+ const int yy[] = { 0, 0, 0,-1,+1};
+
+ int oldx = x;
+ int oldy = y;
+ int i;
+
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+// assert(x in range, y in range);
PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
- for (i = 0; i < 5; i++)
- {
- x = oldx + xx[i];
- y = oldy + yy[i];
-
- if (IsMapFieldEmpty(x - 1, y + 0))
- {
- mis = MakeMissile(spell->Missile,
- x * TileSizeX +
TileSizeX / 2,
- y * TileSizeY +
TileSizeY / 2,
- x * TileSizeX +
TileSizeX / 2,
- y * TileSizeY +
TileSizeY / 2);
- mis->TTL = spell->SpellAction->runes.TTL;
- mis->Controller = SpellRunesController;
- caster->Mana -= spell->ManaCost / 5;
- }
+ for (i = 0; i < 5; i++) {
+ x = oldx + xx[i];
+ y = oldy + yy[i];
+
+ if (IsMapFieldEmpty(x - 1, y + 0)) {
+ mis = MakeMissile(spell->Missile,
+ x * TileSizeX + TileSizeX / 2,
+ y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2,
+ y * TileSizeY + TileSizeY / 2);
+ mis->TTL = spell->SpellAction->runes.TTL;
+ mis->Controller = SpellRunesController;
+ caster->Mana -= spell->ManaCost / 5;
}
+ }
return 0;
}
/**
-** Cast eye of vision. (summon)
+** Cast summon spell.
**
** @param caster Unit that casts the spell
** @param spell Spell-type pointer
@@ -1222,15 +1063,15 @@
global int CastSummon(Unit* caster, const SpellType* spell, Unit* target,
int x, int y)
{
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
- assert(spell->SpellAction->summon.unittype != NULL);
-// assert(x in range, y in range);
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+ assert(spell->SpellAction->Summon.UnitType != NULL);
+// assert(x in range, y in range);
caster->Mana -= spell->ManaCost;
// FIXME: johns: the unit is placed on the wrong position
- target = MakeUnit(spell->SpellAction->summon.unittype, caster->Player);
+ target = MakeUnit(spell->SpellAction->Summon.UnitType, caster->Player);
target->X = x;
target->Y = y;
DropOutOnSide(target, LookingW, 0, 0);
@@ -1262,16 +1103,16 @@
{
Missile *mis = NULL;
- assert(caster);
- assert(spell);
- assert(spell->SpellAction);
-// assert(x in range, y in range);
+ assert(caster);
+ assert(spell);
+ assert(spell->SpellAction);
+// assert(x in range, y in range);
caster->Mana -= spell->ManaCost;
PlayGameSound(spell->SoundWhenCast.Sound, MaxSampleVolume);
mis = MakeMissile(spell->Missile,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
- x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2,
+ x * TileSizeX + TileSizeX / 2, y * TileSizeY + TileSizeY / 2);
mis->TTL = spell->SpellAction->whirlwind.TTL;
mis->Controller = SpellWhirlwindController;
return 0;
@@ -1281,168 +1122,118 @@
// Specific conditions
// ****************************************************************************
-/* *************************************
-** property of unittype himself
+/*
+** Check for unittype properties of unittype himself
*/
-global int CheckUnitTypeFlag(const t_Conditions *condition,
- const
Unit* caster,
- const
Unit* target, int x, int y)
-{
- assert(caster != NULL);
- assert(condition != NULL);
-
- if (target == NULL)
- return !condition->expectvalue;
- // FIXME Modify unit struture for an array of boolean ?
- switch (condition->u.flag)
- {
- case flag_coward:
- {
- return target->Type->Coward;
- }
- case flag_organic:
- {
- return target->Type->Organic;
- }
- case flag_isundead:
- {
- return target->Type->IsUndead;
- }
- case flag_canattack:
- {
- return target->Type->CanAttack;
- }
- case flag_building:
- {
- return target->Type->Building;
- }
- default:
- {
- assert(0);
- // Warn devellopers
- }
- }
+global int CheckUnitTypeFlag(const t_Conditions *condition,
+ const Unit* caster,const Unit* target, int x, int y)
+{
+ assert(caster != NULL);
+ assert(condition != NULL);
+
+ if (target == NULL)
+ return !condition->expectvalue;
+ // FIXME Modify unit struture for an array of boolean ?
+ switch (condition->u.flag) {
+ case flag_coward:
+ return target->Type->Coward;
+ case flag_organic:
+ return target->Type->Organic;
+ case flag_isundead:
+ return target->Type->IsUndead;
+ case flag_canattack:
+ return target->Type->CanAttack;
+ case flag_building:
+ return target->Type->Building;
+ default:
+ assert(0);
+ // Warn devellopers
+ }
}
-/* *************************************
-** property of alliance
+/*
+** Check for alliance status.
*/
-global int CheckAllied(const t_Conditions *condition,
- const Unit* caster,
- const Unit* target, int
x, int y)
+global int CheckAllied(const t_Conditions *condition,const Unit* caster,const
Unit* target, int x, int y)
{
- assert(caster != NULL);
-
- return caster->Player == target->Player
- ||IsAllied(caster->Player, target) ? 1 : 0;
+ assert(caster != NULL);
+ return caster->Player == target->Player || IsAllied(caster->Player,
target) ? 1 : 0;
}
-/* *************************************
-** property of alliance
+/*
+** Check if target is self
*/
-global int Checkhimself(const t_Conditions *condition,
- const Unit* caster,
- const Unit* target, int
x, int y)
+global int Checkhimself(const t_Conditions *condition,const Unit* caster,const
Unit* target, int x, int y)
{
- assert(caster != NULL);
-
- return caster == target;
+ assert(caster != NULL);
+ return caster == target;
}
-/* *************************************
-** property of target unit itself (no type specific)
+/*
+** Check duration effects.
*/
-global int CheckUnitDurationEffect(const t_Conditions
*condition,
-
const Unit* caster,
-
const Unit* target, int x, int y)
+global int CheckUnitDurationEffect(const t_Conditions *condition,const Unit*
caster,const Unit* target, int x, int y)
{
- int ttl;
- assert(condition);
- ttl = condition->u.durationeffect.ttl;
+ int ttl;
+ assert(condition);
+ ttl = condition->u.durationeffect.ttl;
- if (target == NULL)
- return !condition->expectvalue;
+ if (target == NULL) {
+ return !condition->expectvalue;
+ }
- switch (condition->u.durationeffect.flag)
- {
- case flag_invisibility:
- {
- return (target->Invisible >= ttl / CYCLES_PER_SECOND);
- }
- case flag_bloodlust:
- {
- return (target->Bloodlust >= ttl / CYCLES_PER_SECOND);
- }
- case flag_slow:
- {
- return (target->Slow >= ttl / CYCLES_PER_SECOND);
- }
- case flag_haste:
- {
- return (target->Haste >= ttl / CYCLES_PER_SECOND);
- }
- case flag_unholyarmor:
- {
- return (target->UnholyArmor >= ttl / CYCLES_PER_SECOND);
- }
- case flag_flameshield:
- {
- return (target->FlameShield >= ttl);
- }
- case flag_HP:
- {
- return (target->HP >= ttl);
- }
- case flag_Mana:
- {
- return (target->Mana >= ttl);
- }
- case flag_HP_percent:
- {
- return (target->HP * 100 >= ttl *
target->Stats->HitPoints); // FIXME
- }
- case flag_Mana_percent:
- {
- return (target->Mana * 100 >= ttl *
target->Type->_MaxMana); // FIXME
- }
- /// Add here the other cases
- default:
- {
- abort();
- // Warn devellopers
- }
- }
+ switch (condition->u.durationeffect.flag) {
+ case flag_invisibility:
+ return (target->Invisible >= ttl / CYCLES_PER_SECOND);
+ case flag_bloodlust:
+ return (target->Bloodlust >= ttl / CYCLES_PER_SECOND);
+ case flag_slow:
+ return (target->Slow >= ttl / CYCLES_PER_SECOND);
+ case flag_haste:
+ return (target->Haste >= ttl / CYCLES_PER_SECOND);
+ case flag_unholyarmor:
+ return (target->UnholyArmor >= ttl / CYCLES_PER_SECOND);
+ case flag_flameshield:
+ return (target->FlameShield >= ttl);
+ case flag_HP:
+ return (target->HP >= ttl);
+ case flag_Mana:
+ return (target->Mana >= ttl);
+ case flag_HP_percent:
+ return (target->HP * 100 >= ttl * target->Stats->HitPoints); //
FIXME
+ case flag_Mana_percent:
+ return (target->Mana * 100 >= ttl * target->Type->_MaxMana); //
FIXME : MaxMana.
+ /// Add here the other cases
+ default:
+ abort();
+ // Warn devellopers
+ }
}
// ****************************************************************************
// Specific conditions
// ****************************************************************************
-global int CheckEnemyPresence(const t_Conditions *condition,
- const Unit* caster)
+global int CheckEnemyPresence(const t_Conditions *condition,const Unit* caster)
{
- Unit* table[UnitMax];
+ Unit* table[UnitMax];
int i;
int n;
- int range = condition->u.range;
- int x = caster->X;
- int y = caster->Y;
+ int range = condition->u.range;
+ int x = caster->X;
+ int y = caster->Y;
- assert(condition != NULL);
- assert(caster != NULL);
+ assert(condition != NULL);
+ assert(caster != NULL);
// +1 should be + Caster_tile_Size ?
- n = SelectUnits(x - range, y - range,
- x + range + 1, y + range + 1,
- table);
- for (i = 0; i < n; ++i)
- {
- if (IsEnemy(caster->Player, table[i]))
- {
- return 1;
- }
+ n = SelectUnits(x - range, y - range,x + range + 1, y + range + 1,table);
+ for (i = 0; i < n; ++i) {
+ if (IsEnemy(caster->Player, table[i])) {
+ return 1;
}
- return 0;
+ }
+ return 0;
}
// ****************************************************************************
@@ -1451,7 +1242,7 @@
local Target *NewTarget(TargetType t, const Unit *unit, int x, int y)
{
- Target *target = (Target *) malloc(sizeof(*target));
+ Target *target = (Target *) malloc(sizeof(*target));
assert(!(unit == NULL && t == TargetUnit));
assert(!(!(0 <= x && x < TheMap.Width) && t == TargetPosition));
@@ -1469,15 +1260,14 @@
return NewTarget(TargetNone, NULL, 0, 0);
}
-local Target *NewTargetUnit(const Unit *unit)
+local Target *NewTargetUnit(const Unit *unit)
{
assert(unit != NULL);
-
return NewTarget(TargetUnit, unit, 0, 0);
}
-local Target *NewTargetPosition(int x, int y)
+local Target *NewTargetPosition(int x, int y)
{
assert(0 <= x && x < TheMap.Width);
assert(0 <= y && y < TheMap.Height);
@@ -1494,30 +1284,27 @@
*/
local int PassGenericCondition(const Unit* caster,const SpellType* spell,const
t_Conditions *condition)
{
-// const t_Conditions *condition = NULL;
- int ret;
+ int ret;
- assert(caster != NULL);
- assert(spell != NULL);
+ assert(caster != NULL);
+ assert(spell != NULL);
- // FIXME : Move it in spell->Condition_generic ???
- // mana is a must!
- if (caster->Mana < spell->ManaCost)
- {
- return 0;
- }
- for (/*condition = spell->Condition_generic*/; condition != NULL;
condition = condition->next)
- {
- assert(condition->f.generic != NULL);
- ret = condition->f.generic(condition, caster);
- assert(ret == 0 || ret == 1);
- assert(condition->expectvalue == 0 || condition->expectvalue ==
1);
- if (ret != condition->expectvalue)
- {
- return 0;
- }
+ // FIXME : Move it in spell->Condition_generic ???
+ // mana is a must!
+ if (caster->Mana < spell->ManaCost) {
+ return 0;
+ }
+ for (/*condition = spell->Condition_generic*/; condition != NULL;
condition = condition->next)
+ {
+ assert(condition->f.generic != NULL);
+ ret = condition->f.generic(condition, caster);
+ assert(ret == 0 || ret == 1);
+ assert(condition->expectvalue == 0 || condition->expectvalue == 1);
+ if (ret != condition->expectvalue) {
+ return 0;
}
- return 1;
+ }
+ return 1;
}
/**
@@ -1525,36 +1312,29 @@
** @return 1 if condition is ok.
** @return 0 else.
*/
-local int PassSpecificCondition(const Unit* caster,
-
const SpellType* spell,
-
const Unit* target, // FIXME : Use an unique struture t_Target ?
-
int x,
- int
y,
-
const t_Conditions *condition)
-{
-// const t_Conditions *condition = NULL;
- int ret;
-
- assert(caster != NULL);
- assert(spell != NULL);
-
- for (/*condition = spell->Condition_specific*/; condition != NULL;
condition = condition->next)
- {
- assert(condition->f.specific != NULL);
- ret = condition->f.specific(condition, caster, target, x, y);
- assert(ret == 0 || ret == 1);
- assert(condition->expectvalue == 0 || condition->expectvalue ==
1);
- if (ret != condition->expectvalue)
- {
- return 0;
- }
+local int PassSpecificCondition(const Unit* caster,const SpellType* spell,
+ const Unit* target,int x,int y,const t_Conditions *condition)
+{
+ int ret;
+
+ assert(caster != NULL);
+ assert(spell != NULL);
+
+ for (/*condition = spell->Condition_specific*/; condition != NULL;
condition = condition->next) {
+ assert(condition->f.specific != NULL);
+ ret = condition->f.specific(condition, caster, target, x, y);
+ assert(ret == 0 || ret == 1);
+ assert(condition->expectvalue == 0 || condition->expectvalue == 1);
+ if (ret != condition->expectvalue) {
+ return 0;
}
- return 1;
+ }
+ return 1;
}
/**
-** Select the target for the autocast.
+** Select the target for the autocast.
**
** @param caster Unit who would cast the spell.
** @param spell Spell-type pointer.
@@ -1562,88 +1342,71 @@
** @return Target* choosen target or Null if spell can't be cast.
**
*/
-// should be global (for IA) ???
-local Target *SelectTargetUnitsOfAutoCast(const Unit *caster,
-
const SpellType *spell)
-{
- assert(spell != NULL);
- assert(spell->AutoCast != NULL);
- assert(caster != NULL);
-
- switch (spell->Target)
- {
- case TargetSelf :
- {
- return NewTargetUnit(caster);
- }
- case TargetNone :
- {
- return NewTargetNone();
- }
- case TargetPosition:
- {
- int x, y;
- int range = spell->AutoCast->Range;
-
- do
- {
- x = caster->X + SyncRand() % (2 * range) -
range;
- y = caster->Y + SyncRand() % (2 * range) -
range;
- } while (x < 0 && x <= TheMap.Width
- && y < 0 && y <= TheMap.Height);
-
- // FIXME : CHOOSE a better POSITION (add info in
structure ???)
- // Just good enought for holyvision...
- return NewTargetPosition(SyncRand() % TheMap.Width,
-
SyncRand() % TheMap.Height);
+// should be global (for AI) ???
+local Target *SelectTargetUnitsOfAutoCast(const Unit *caster,const SpellType
*spell)
+{
+ Unit* table[UnitMax];
+ int x;
+ int y;
+ int range;
+ int nb_units;
+ int i;
+ int j;
+
+ assert(spell != NULL);
+ assert(spell->AutoCast != NULL);
+ assert(caster != NULL);
+
+ switch (spell->Target) {
+ case TargetSelf :
+ return NewTargetUnit(caster);
+ case TargetNone :
+ return NewTargetNone();
+ case TargetPosition:
+ range = spell->AutoCast->Range;
+ do {
+ x = caster->X + SyncRand() % (2 * range) - range;
+ y = caster->Y + SyncRand() % (2 * range) - range;
+ } while (x < 0 && x <= TheMap.Width
+ && y < 0 && y <= TheMap.Height);
+
+ // FIXME : CHOOSE a better POSITION (add info in structure ???)
+ // Just good enought for holyvision...
+ return NewTargetPosition(x, y);
+ case TargetUnit:
+ x=caster->X;
+ y=caster->Y;
+ range=spell->AutoCast->Range;
+ // ( + 1) would be ( + caster->size) ??
+ nb_units = SelectUnits(caster->X - range, caster->Y - range,
+ caster->X + range + 1, caster->Y + range + 1,table);
+ // For all Unit, check if it is a possible target
+ for (i = 0, j = 0; i < nb_units; i++) {
+ if
(PassSpecificCondition(caster,spell,table[i],x,y,spell->Condition_specific)
+ &&
PassSpecificCondition(caster,spell,table[i],x,y,spell->AutoCast->Condition_specific))
{
+ table[j++] = table[i];
}
- case TargetUnit:
- {
- Unit* table[UnitMax];
- int range = spell->AutoCast->Range;
- int nb_units;
- int x = caster->X;
- int y = caster->Y;
- int i, j;
- // ( + 1) would be ( + caster->size) ??
- nb_units = SelectUnits(caster->X - range, caster->Y - range,
- caster->X +
range + 1, caster->Y + range + 1,
- table);
- // For all Unit, check if it is a possible target
- for (i = 0, j = 0; i < nb_units; i++)
- {
- if (PassSpecificCondition(caster, spell,
table[i], x, y,
- spell->Condition_specific)
- && PassSpecificCondition(caster, spell,
table[i], x, y,
-
spell->AutoCast->Condition_specific))
- {
- table[j++] = table[i];
- }
- }
- nb_units = j;
- if (nb_units != 0)
- {
+ }
+ nb_units = j;
+ if (nb_units != 0) {
#if 0
// For the best target
- sort(table, nb_units, spell->autocast->f_order);
- return NewTargetUnit(table[0]);
+ sort(table, nb_units, spell->autocast->f_order);
+ return NewTargetUnit(table[0]);
#else
// For a random valid target
- i = SyncRand() % nb_units;
- return NewTargetUnit(table[i]);
+ i = SyncRand() % nb_units;
+ return NewTargetUnit(table[i]);
#endif
- }
- break;
- }
- default:
- {
- // Error : add the new cases
- // FIXME : Warn developpers
- return NULL;
- break;
- }
+ }
+ break;
+ default:
+ // Error : add the new cases
+ // FIXME : Warn developpers
+ return NULL;
+ break;
}
- return NULL; // Can't spell the auto-cast.
+ return NULL; // Can't spell the auto-cast.
}
// ****************************************************************************
@@ -1667,10 +1430,7 @@
global void DoneSpells()
{
// FIXME
-#if 0
-
-#endif
- free(SpellTypeTable);
+ free(SpellTypeTable);
// nothing yet
}
@@ -1744,6 +1504,22 @@
// ****************************************************************************
/**
+** Check if spell is research for player \p player.
+** @param player : player for who we want to know if he knows the spell.
+** @param id :
+*/
+global int SpellIsAvailable(const Player* player, int SpellId)
+{
+ assert(player != NULL);
+ assert(0 <= SpellId && SpellId < SpellTypeCount);
+
+ int dependencyId = SpellTypeTable[SpellId].DependencyId;
+
+ return dependencyId == -1 || UpgradeIdAllowed(player, dependencyId) == 'R';
+}
+
+
+/**
** Check if the spell can be auto cast.
**
** @param spell Spell-type pointer
@@ -1752,9 +1528,9 @@
*/
global int CanAutoCastSpell(const SpellType* spell)
{
- assert(spell != NULL);
+ assert(spell != NULL);
- return spell->AutoCast ? 1 : 0;
+ return spell->AutoCast ? 1 : 0;
}
/**
@@ -1796,34 +1572,29 @@
**
** @return 1 if spell is casted, 0 if not.
*/
-global int AutoCastSpell(Unit *caster,
- const SpellType* spell)
+global int AutoCastSpell(Unit *caster,const SpellType* spell)
{
- Target *target = NULL;
+ Target *target = NULL;
- assert(caster != NULL);
- assert(spell != NULL);
- assert(0 <= spell->Ident && spell->Ident < SpellTypeCount);
+ assert(caster != NULL);
+ assert(spell != NULL);
+ assert(0 <= spell->Ident && spell->Ident < SpellTypeCount);
assert(caster->Type->CanCastSpell);
assert(caster->Type->CanCastSpell[spell->Ident]);
- if (!PassGenericCondition(caster, spell, spell->Condition_generic)
- || !PassGenericCondition(caster, spell,
spell->AutoCast->Condition_generic))
- {
- return 0;
- }
- target = SelectTargetUnitsOfAutoCast(caster, spell);
- if (target == NULL)
- {
- return 0;
- }
- else
- {
- // Must move before ?
- // FIXME SpellType* of CommandSpellCast must be const.
- CommandSpellCast(caster, target->X, target->Y, target->unit,
(SpellType*) spell, FlushCommands);
- free(target);
- }
+ if (!PassGenericCondition(caster, spell, spell->Condition_generic)
+ || !PassGenericCondition(caster, spell,
spell->AutoCast->Condition_generic)) {
+ return 0;
+ }
+ target = SelectTargetUnitsOfAutoCast(caster, spell);
+ if (target == NULL) {
+ return 0;
+ } else {
+ // Must move before ?
+ // FIXME SpellType* of CommandSpellCast must be const.
+ CommandSpellCast(caster, target->X, target->Y, target->unit,
(SpellType*) spell, FlushCommands);
+ free(target);
+ }
return 1;
}
@@ -1838,12 +1609,12 @@
**
** @return !=0 if spell should/can continue or 0 to stop
*/
-global int SpellCast(Unit* caster, const SpellType* spell,
- Unit* target, int x, int y)
+global int SpellCast(Unit* caster, const SpellType* spell,Unit* target, int x,
int y)
{
assert(spell != NULL);
assert(spell->f != NULL);
assert(caster != NULL);
+ assert(SpellIsAvailable(caster->Player, spell->Ident));
caster->Invisible = 0;// unit is invisible until attacks // FIXME Must be
configurable
if (target) {
Index: stratagus/src/include/spells.h
diff -u stratagus/src/include/spells.h:1.23 stratagus/src/include/spells.h:1.24
--- stratagus/src/include/spells.h:1.23 Fri Sep 26 05:15:22 2003
+++ stratagus/src/include/spells.h Fri Sep 26 11:47:51 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.h,v 1.23 2003/09/26 09:15:22 mr-russ Exp $
+// $Id: spells.h,v 1.24 2003/09/26 15:47:51 n0body Exp $
#ifndef __SPELLS_H__
#define __SPELLS_H__
@@ -98,22 +98,19 @@
// TTL's below are in ticks: approx: 500=13sec, 1000=25sec, 2000=50sec
// FIXME use TTL, as in TICKS to live
struct {
- int Fields; /// FIXME doc
- int Shards; /// FIXME doc
- int Damage; /// damage
- } Blizzard;
+ int Fields; /// The size of the affected square
+ int Shards; /// Number of shards thrown.
+ int Damage; /// Damage for every shard.
+ /// The offset of the missile start point to the hit location.
+ int StartOffsetX;
+ int StartOffsetY;
+ } AreaBombardment;
struct {
UnitType *PortalType; /// The unit type spawned
} SpawnPortal;
struct {
- int Fields; /// FIXME doc
- int Shards; /// FIXME doc
- int Damage; /// damage
- } DeathAndDecay;
-
- struct {
int TTL; /// time to live (ticks)
int Damage; /// Damage.
} Fireball;
@@ -143,24 +140,28 @@
} invisibility;
struct {
- UnitType *unit; /// The new form :)
- } polymorph;
+ UnitType *NewForm; /// The new form
+ // TODO: temporary polymorphs would be awesome, but hard to implement
+ } Polymorph;
struct {
- UnitType *skeleton; /// The unit to spwan from corpses
- } raisedead;
+ UnitType *UnitType; /// Type of unit to be summoned.
+ int TTL; /// Time to live for summoned unit. 0 means
infinite
+ } Summon;
struct {
- int TTL; /// time to live (ticks)
- int damage; /// Damage.
- } runes;
-
+ UnitType *Skeleton; /// The unit to spawn from corpses
+ int TTL; /// Time to live for summon. 0 means infinite.
+ } RaiseDead;
+ // What about a resurection spell?
+
struct {
- UnitType *unittype; /// Type of unit to be summoned.
- } summon;
+ int TTL; /// time to live (ticks)
+ int Damage; /// Damage.
+ } runes;
struct {
- int TTL; /// time to live (ticks)
+ int TTL; /// time to live (ticks)
// FIXME: more configurations
} whirlwind;
} SpellActionType;
@@ -246,7 +247,7 @@
/*
** Pointer on function that cast the spell.
*/
-typedef int f_spell(Unit* caster, const struct _spell_type_* spell, Unit*
target,
+typedef int SpellFunc(Unit* caster, const struct _spell_type_* spell, Unit*
target,
int x, int y);
/**
@@ -260,7 +261,7 @@
// Spell Specifications
TargetType Target; /// Targetting information. See
TargetType.
- f_spell *f; /// function to cast the spell.
+ SpellFunc *f; /// function to cast the spell.
SpellActionType *SpellAction; /// More arguments for spell (damage,
delay, additional sounds...).
int Range; /// Max range of the target.
int ManaCost; /// required mana for each cast
@@ -337,21 +338,20 @@
** Spelltype to cast.
*/
-f_spell CastHolyVision;
-f_spell CastHealing;
-f_spell CastHaste;
-f_spell CastFireball;
-f_spell CastFlameShield;
-f_spell CastInvisibility;
-f_spell CastPolymorph;
-f_spell CastBlizzard;
-f_spell CastSummon;
-f_spell CastRunes;
-f_spell CastDeathCoil;
-f_spell CastRaiseDead;
-f_spell CastWhirlwind;
-f_spell CastDeathAndDecay;
-f_spell CastCircleOfPower;
+SpellFunc CastHolyVision;
+SpellFunc CastHealing;
+SpellFunc CastHaste;
+SpellFunc CastFireball;
+SpellFunc CastFlameShield;
+SpellFunc CastInvisibility;
+SpellFunc CastPolymorph;
+SpellFunc CastAreaBombardment;
+SpellFunc CastSummon;
+SpellFunc CastRunes;
+SpellFunc CastDeathCoil;
+SpellFunc CastRaiseDead;
+SpellFunc CastWhirlwind;
+SpellFunc CastSpawnPortal;
/*
Index: stratagus/src/siod/slib.c
diff -u stratagus/src/siod/slib.c:1.27 stratagus/src/siod/slib.c:1.28
--- stratagus/src/siod/slib.c:1.27 Tue Sep 23 05:12:35 2003
+++ stratagus/src/siod/slib.c Fri Sep 26 11:47:51 2003
@@ -94,7 +94,7 @@
static void init_slib_version(void)
{setvar(cintern("*slib-version*"),
- cintern("$Id: slib.c,v 1.27 2003/09/23 09:12:35 martinxyz Exp $"),
+ cintern("$Id: slib.c,v 1.28 2003/09/26 15:47:51 n0body Exp $"),
NIL);}
char * __stdcall siod_version(void)
@@ -585,66 +585,64 @@
long repl(struct repl_hooks *h)
{
-
- LISP x, cw = 0;
- double rt,ct;
- assert(h != NULL);
- while(1)
+ LISP x, cw = 0;
+ double rt,ct;
+ assert(h != NULL);
+ while(1) {
+ if ((gc_kind_copying == 1) &&
+ ((gc_status_flag) || heap >= heap_end)) {
+ rt = myruntime();
+ gc_stop_and_copy();
+ if (siod_verbose_level >= 2) {
+ sprintf(tkbuffer,"GC took %g seconds, %ld compressed to %ld,
%ld free\n",
+
myruntime()-rt,old_heap_used,(long)(heap-heap_org),(long)(heap_end-heap));
+ grepl_puts(tkbuffer, h->repl_puts);
+ }
+ }
+ if (siod_verbose_level >= 2) {
+ grepl_puts("> ", h->repl_puts);
+ }
+ if (h->repl_read == NULL) {
+ x = lread(NIL);
+ } else {
+ x = (*h->repl_read)();
+ }
+ if EQ(x,eof_val) {
+ break;
+ }
+ rt = myruntime();
+ ct = myrealtime();
+ if (gc_kind_copying == 1) {
+ cw = heap;
+ } else {
+ gc_cells_allocated = 0;
+ gc_time_taken = 0.0;
+ }
+ if (h->repl_eval == NULL) {
+ x = leval(x,NIL);
+ } else {
+ x = (*h->repl_eval)(x);
+ }
+ if (gc_kind_copying == 1)
{
- if (gc_kind_copying == 1 &&
- ((gc_status_flag) || heap >= heap_end))
- {
- rt = myruntime();
- gc_stop_and_copy();
- if (siod_verbose_level >= 2)
- {sprintf(tkbuffer,
- "GC took %g seconds, %ld compressed to %ld,
%ld free\n",
-
myruntime()-rt,old_heap_used,(long)(heap-heap_org),(long)(heap_end-heap));
- grepl_puts(tkbuffer, h->repl_puts);
- }
- }
- /*
- if (siod_verbose_level >= 2)
- grepl_puts("> ", h->repl_puts);
- */
- if (h->repl_read == NULL)
- x = lread(NIL);
- else
- x = (*h->repl_read)();
- if EQ(x,eof_val) break;
- rt = myruntime();
- ct = myrealtime();
- if (gc_kind_copying == 1)
- cw = heap;
- else
- {gc_cells_allocated = 0;
- gc_time_taken = 0.0;}
- if (h->repl_eval == NULL)
- x = leval(x,NIL);
- else
- x = (*h->repl_eval)(x);
- if (gc_kind_copying == 1)
- sprintf(tkbuffer,
- "Evaluation took %g seconds %ld cons work, %g
real.\n",
- myruntime()-rt,
- (long)(heap-cw),
- myrealtime()-ct);
- else
- sprintf(tkbuffer,
- "Evaluation took %g seconds (%g in gc) %ld cons
work, %g real.\n",
- myruntime()-rt,
- gc_time_taken,
- gc_cells_allocated,
- myrealtime()-ct);
- if (siod_verbose_level >= 2)
- grepl_puts(tkbuffer,h->repl_puts);
- if (h->repl_print == NULL)
- {if (siod_verbose_level >= 2)
- lprint(x,NIL);}
- else
- (*h->repl_print)(x);
- }
- return(0);
+ sprintf(tkbuffer,"Evaluation took %g seconds %ld cons work, %g
real.\n",
+ myruntime()-rt,(long)(heap-cw),myrealtime()-ct);
+ } else {
+ sprintf(tkbuffer, "Evaluation took %g seconds (%g in gc) %ld cons
work, %g real.\n",
+
myruntime()-rt,gc_time_taken,gc_cells_allocated,myrealtime()-ct);
+ }
+ if (siod_verbose_level >= 2) {
+ grepl_puts(tkbuffer,h->repl_puts);
+ }
+ if (h->repl_print == NULL) {
+ if (siod_verbose_level >= 2) {
+ lprint(x,NIL);
+ }
+ } else {
+ (*h->repl_print)(x);
+ }
+ }
+ return(0);
}
void set_fatal_exit_hook(void (*fcn)(void))
@@ -940,6 +938,8 @@
{char *tmp;
tmp = (char *) malloc((size) ? size : 1);
if (tmp == (char *)NULL) errl("failed to allocate storage from system",NIL);
+ // FIXME: This should be necesary, but it's better to be safe.
+ memset(tmp,0,(size)?size:1);
return(tmp);}
LISP gen_intern(char *name,long copyp)
@@ -1021,7 +1021,6 @@
void __stdcall init_storage(void)
{long j;
LISP stack_start;
-
#ifdef DEBUG
stack_start = NULL;
#endif
@@ -1418,13 +1417,14 @@
long looks_pointerp(LISP p)
{long j;
LISP h;
- for(j=0;j<nheaps;++j)
+ for(j=0;j<nheaps;++j) {
if ((h = heaps[j]) &&
(p >= h) &&
(p < (h + heap_size)) &&
(((((char *)p) - ((char *)h)) % sizeof(struct obj)) == 0) &&
NTYPEP(p,tc_free_cell))
return(1);
+ }
return(0);}
void mark_locations_array(LISP *x,long n)
- [Stratagus-CVS] stratagus data/ccl/spells.ccl src/action/action...,
Crestez Leonard <=