[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: |
Mon, 29 Sep 2003 13:04:15 -0400 |
CVSROOT: /cvsroot/stratagus
Module name: stratagus
Branch:
Changes by: Crestez Leonard <address@hidden> 03/09/29 13:04:15
Modified files:
data/ccl : spells.ccl
src/action : action_spellcast.c actions.c
src/clone : ccl_spell.c spells.c
src/include : spells.h
Log message:
Lots of spell work. Rewrite conditions. Fix mana bug.
Patches:
Index: stratagus/data/ccl/spells.ccl
diff -u stratagus/data/ccl/spells.ccl:1.3 stratagus/data/ccl/spells.ccl:1.4
--- stratagus/data/ccl/spells.ccl:1.3 Sat Sep 27 15:05:47 2003
+++ stratagus/data/ccl/spells.ccl Mon Sep 29 13:04:11 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.3 2003/09/27 19:05:47 n0body Exp $
+;; $Id: spells.ccl,v 1.4 2003/09/29 17:04:11 n0body Exp $
;; For documentation see stratagus/doc/ccl/ccl.html ;; FIXME write and move
doc.
@@ -95,12 +95,12 @@
(define-spell "spell-holy-vision"
'showname "Holy Vision"
'manacost 70
- 'range -1
+ 'range 'infinite
'target 'position
- 'action '(summon unit-type unit-revealer time-to-live 100)
+ 'action '(summon unit-type unit-revealer time-to-live 10)
'sound-when-cast "holy vision"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range -1)
+; 'autocast '(range -1)
)
(define-spell "spell-healing"
@@ -108,18 +108,23 @@
'manacost 6
'range 6
'target 'unit
- 'action '(adjust-vitals hit-points +1)
- 'condition '( UnitTypeflag (true organic)
- UnitTypeflag (false building)
- DurationEffect (false flag HP_percent value 100) ;; HP
< 100% HPMAX
- Alliance true
- )
+ 'action '(adjust-vitals hit-points 1)
+ 'condition '(
+ organic only
+ building false
+ max-hp-percent 100)
'sound-when-cast "healing"
'missile-when-cast "missile-heal-effect"
'autocast '(range 6
- condition (UnitTypeflag (false coward)
- )
- )
+ condition (
+ coward false
+ alliance only
+ ;; 50% in battle, 100 while waiting? could be an idea
+ ;; This way we could stop healing all the time, just when an
+ ;; unit drops under 50 percent.
+ max-hp-percent 100
+ )
+ )
)
(define-spell "spell-exorcism"
@@ -128,13 +133,14 @@
'range 10
'target 'unit
'action '(adjust-vitals hit-points -1)
- 'condition '( UnitTypeflag (true undead)
- UnitTypeflag (false building)
- Alliance false
- )
+ 'condition '(
+ undead only
+ building false ; any undead buildings?
+ alliance false
+ )
'sound-when-cast "exorcism"
'missile-when-cast "missile-exorcism"
- 'autocast '(range 10 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 10 condition (coward false alliance false))
)
(define-spell "spell-eye-of-vision"
@@ -154,13 +160,13 @@
'range 6
'target 'unit
'action '(adjust-buffs haste-ticks 1000 slow-ticks 0)
- 'condition '( UnitTypeflag (false building)
- DurationEffect (false flag haste value 900) ;; haste <
900 / CYCLE_PER_SECOND
- Alliance true
- )
+ 'condition '(
+ building false
+ max-haste-ticks 10 ;; FIXME: proper value?
+ )
'sound-when-cast "haste"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 6 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 6 condition (coward false alliance only))
)
(define-spell "spell-slow"
@@ -169,13 +175,12 @@
'range 10
'target 'unit
'action '(adjust-buffs slow-ticks 1000 haste-ticks 0)
- 'condition '( UnitTypeflag (false building)
- DurationEffect (false flag slow value 900) ;; slow <
900 / CYCLE_PER_SECOND
- Alliance true
- )
+ 'condition '(
+ building false
+ max-slow-ticks 10)
'sound-when-cast "slow"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 10 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 10 condition (coward false alliance only))
)
(define-spell "spell-bloodlust"
@@ -184,13 +189,12 @@
'range 6
'target 'unit
'action '(adjust-buffs bloodlust-ticks 1000)
- 'condition '( UnitTypeflag (true organic)
- DurationEffect (false flag bloodlust value 900) ;;
bloodlust < 900 / CYCLE_PER_SECOND
- Alliance true
- )
+ 'condition '(
+ organic only
+ max-bloodlust-ticks 10)
'sound-when-cast "bloodlust"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 6 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 6 condition (coward false alliance only))
)
(define-spell "spell-invisibility"
@@ -199,13 +203,12 @@
'range 6
'target 'unit
'action '(adjust-buffs invisibility-ticks 2000)
- 'condition '( UnitTypeflag (false building)
- DurationEffect (false flag invisibility value 900) ;;
invisibility < 900 / CYCLE_PER_SECOND
- Alliance true
- )
+ 'condition '(
+ building false
+ max-invisibility-ticks 10)
'sound-when-cast "invisibility"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 6 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 6 condition (coward false))
)
(define-spell "spell-unholy-armor"
@@ -214,13 +217,12 @@
'range 6
'target 'unit
'action '(adjust-buffs invincibility-ticks 500)
- 'condition '(UnitTypeflag (false building)
- DurationEffect (false flag unholyarmor value 900) ;;
unholyarmor < 900 / CYCLE_PER_SECOND
- Alliance true
- )
+ 'condition '(
+ building false
+ max-invincibility-ticks 10)
'sound-when-cast "unholyarmor"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 6 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 6 condition (coward false alliance only))
)
(define-spell "spell-flame-shield"
@@ -229,13 +231,12 @@
'range 6
'target 'unit
'action '(flame-shield duration 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
+ ;; I think it's better if we can cast it multiple times and the effects
stack.
+ ;; Can be casted, and is effective on both allies and enemies
+ 'condition '(building false)
'sound-when-cast "flame shield"
'missile-when-cast "missile-flame-shield" ; NOT use
- 'autocast '(range 6 condition (UnitTypeflag (false coward)))
+ 'autocast '(range 6 condition (coward false))
)
(define-spell "spell-polymorph"
@@ -244,12 +245,11 @@
'range 10
'target 'unit
'action '(polymorph new-form unit-critter)
- 'condition '(UnitTypeflag (true organic)
- Alliance false
- )
+ 'condition '(organic only)
'sound-when-cast "polymorph"
'missile-when-cast "missile-normal-spell"
- 'autocast '(range 10 condition (UnitTypeflag (false coward)))
+ ;; Only cast on the strongest units!!!
+ 'autocast '(range 10 condition (alliance false min-hp-percent 75))
)
Index: stratagus/src/action/action_spellcast.c
diff -u stratagus/src/action/action_spellcast.c:1.32
stratagus/src/action/action_spellcast.c:1.33
--- stratagus/src/action/action_spellcast.c:1.32 Sun Sep 14 00:45:52 2003
+++ stratagus/src/action/action_spellcast.c Mon Sep 29 13:04:12 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: action_spellcast.c,v 1.32 2003/09/14 04:45:52 mr-russ Exp $
+// $Id: action_spellcast.c,v 1.33 2003/09/29 17:04:12 n0body Exp $
/*
** This is inherited from action_attack.c, actually spell casting will
@@ -208,12 +208,14 @@
}
return;
}
+ // FIXME FIXME FIXME: Check if already in range and skip straight to
2(casting)
NewResetPath(unit);
unit->Value=0; // repeat spell on next pass? (defaults to `no')
unit->SubAction=1;
// FALL THROUGH
case 1: // Move to the target.
- if( (spell = unit->Orders[0].Arg1)->Range != 0x7F ) {
+ // FIXME: crashes with huge ranges.
+ if( (spell = unit->Orders[0].Arg1)->Range != INFINITE_RANGE ) {
SpellMoveToTarget(unit);
break;
} else {
Index: stratagus/src/action/actions.c
diff -u stratagus/src/action/actions.c:1.94 stratagus/src/action/actions.c:1.95
--- stratagus/src/action/actions.c:1.94 Sat Sep 27 02:16:36 2003
+++ stratagus/src/action/actions.c Mon Sep 29 13:04:13 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: actions.c,v 1.94 2003/09/27 06:16:36 mr-russ Exp $
+// $Id: actions.c,v 1.95 2003/09/29 17:04:13 n0body Exp $
//@{
@@ -353,7 +353,7 @@
if( unit->TTL && unit->TTL<(GameCycle-unit->HP) ) {
DebugLevel0Fn("Unit must die %lu %lu!\n" _C_ unit->TTL
_C_ GameCycle);
- if( !--unit->HP ) {
+ if( --unit->HP<0 ) {
LetUnitDie(unit);
deadunit|=1;
}
@@ -585,10 +585,6 @@
continue;
}
- if( --unit->Wait ) { // Wait until counter reached
- continue;
- }
-
if( blinkthiscycle && unit->Blink ) { // clear blink flag
--unit->Blink;
}
@@ -609,6 +605,10 @@
}
if( burnthiscycle ) {
BurnBuilding(unit);
+ }
+
+ if( --unit->Wait ) { // Wait until counter reached
+ continue;
}
HandleUnitAction(unit);
Index: stratagus/src/clone/ccl_spell.c
diff -u stratagus/src/clone/ccl_spell.c:1.8 stratagus/src/clone/ccl_spell.c:1.9
--- stratagus/src/clone/ccl_spell.c:1.8 Sat Sep 27 16:27:29 2003
+++ stratagus/src/clone/ccl_spell.c Mon Sep 29 13:04:14 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: ccl_spell.c,v 1.8 2003/09/27 20:27:29 n0body Exp $
+// $Id: ccl_spell.c,v 1.9 2003/09/29 17:04:14 n0body Exp $
//@{
/*----------------------------------------------------------------------------
@@ -318,314 +318,117 @@
}
}
-// **************************************************************************
-// Generic condition parsers for autocast for spell.
-// **************************************************************************
-
-/**
-** To pushback the condition \p cond to the list \p begin.
-** @param begin : begin of the list.
-** @param cond : condition to add.
-*/
-local void pushback_condition(t_Conditions **begin, t_Conditions *cond)
-{
- t_Conditions *next;
-
- DebugCheck(!begin);
- DebugCheck(!cond);
-
- if (*begin == NULL) {
- *begin = cond;
- return ;
- }
- for(next = *begin; next->next != NULL; next = next->next) {
- next->next = cond;
- }
-}
-
-/**
-** Pointer on function to parse 'condition.
-** @param spellName : name of spell modified.
-** @param id : last keyword recognized.
-** @param list : args for \p id.
-** @param generic : list for generic conditions.
-** @param specific : list for specific conditions.
-*/
-typedef void f_ccl_condition(const char *spellname, const char *id, SCM list,
- t_Conditions **generic, t_Conditions **specific);
-
-/**
-** Parsing true or false.
-** factorisation of code.
-** @param SpellName : Name of spell.
-** @param id : last keywork.
-** @param expectvalue : OUTPUT <- 1 if true 0 else
-*/
-local int ccl_true(const char *spellname, const char *id, int *expectvalue,
- SCM value)
-{
- DebugCheck(!spellname);
- DebugCheck(!id);
- DebugCheck(!expectvalue);
-
- *expectvalue = 0;
- if (gh_eq_p(value, gh_symbol2scm("true"))) {
- *expectvalue = 1;
- return 1;
- }
- if (gh_eq_p(value, gh_symbol2scm("false"))) {
- return 1;
- }
-// Warning user : Unknown flag
- DebugLevel0Fn("In spell-type %s : %s : %s\n"
- _C_ spellname _C_ id _C_ "Argument must be true or false");
- return 0;
-}
-
-/**
-** Parse the Condition for spell.
-** list = #t #flagtype
-*/
-local void ccl_UnitTypeFlag(const char *spellname, const char *id, SCM list,
- t_Conditions **generic, t_Conditions **specific)
-{
- SCM value;
- t_Conditions *cond;
- struct {
- const char *id;
- int flag;
- } parser[] = {
- {"building", flag_building},
- {"coward", flag_coward},
- {"canattack", flag_canattack},
- {"organic", flag_organic},
- {"undead", flag_isundead},
- {NULL, 0}
- };
- int i;
-
- DebugCheck(!id);
- DebugCheck(!spellname);
- DebugCheck(!generic);
- DebugCheck(!specific);
-
-
- cond = malloc(sizeof(*cond));
- memset(cond, 0, sizeof(*cond));
- value = gh_car(list);
- if (!ccl_true(spellname, id, &cond->expectvalue, value)) {
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- for (i = 0; parser[i].id != NULL; i++) {
- if (gh_eq_p(value, gh_symbol2scm((char *)parser[i].id))) {
- cond->u.flag = parser[i].flag;
- break;
- }
- }
- if (parser[i].id == NULL) {
- DebugLevel0Fn("FIXME : WARNING : unknow flag");
- free(cond);
- return ;
- }
- cond->f.specific = CheckUnitTypeFlag;
- pushback_condition(specific, cond);
-}
-
-/**
-** Parse the Condition for spell.
-** list = #t #f_flag #n
-*/
-local void ccl_DurationEffect(const char *spellname, const char *id, SCM list,
- t_Conditions **generic, t_Conditions **specific)
-{
- SCM value;
- t_Conditions *cond;
- struct {
- const char *id;
- int flag;
- } parser[] = {
- {"bloodlust", flag_bloodlust},
- {"flameshield", flag_flameshield},
- {"haste", flag_haste},
- {"invisibility", flag_invisibility},
- {"slow", flag_slow},
- {"unholyarmor", flag_unholyarmor},
- {"HP", flag_HP},
- {"mana", flag_Mana},
- {"HP_percent", flag_HP_percent},
- {"mana_percent", flag_Mana_percent},
- {NULL, 0}
- };
- int i;
-
- DebugCheck(!id);
- DebugCheck(!spellname);
- DebugCheck(!generic);
- DebugCheck(!specific);
-
- cond = malloc(sizeof(*cond));
- memset(cond, 0, sizeof(*cond));
- value = gh_car(list);
- if (!ccl_true(spellname, id, &cond->expectvalue, value)) {
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- if (!gh_eq_p(value, gh_symbol2scm("flag"))) {
- DebugLevel0Fn("FIXME : WARNING : unknow flag");
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- for (i = 0; parser[i].id != NULL; i++) {
- if (gh_eq_p(value, gh_symbol2scm((char *)parser[i].id))) {
- cond->u.durationeffect.flag = parser[i].flag;
- break;
- }
- }
- if (parser[i].id == NULL) {
- DebugLevel0Fn("FIXME : WARNING : unknow flag");
- // FIXME : WARNING.
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- if (!gh_eq_p(value, gh_symbol2scm("value"))) {
- DebugLevel0Fn("FIXME : WARNING : unknow flag");
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- cond->u.durationeffect.ttl = gh_scm2int(value);
- cond->f.specific = CheckUnitDurationEffect;
- pushback_condition(specific, cond);
-}
-
-/**
-** For enemy presence
-** list = #t range #n
-*/
-void ccl_enemy_presence(const char *spellname, const char *id, SCM list,
- t_Conditions **generic, t_Conditions **specific)
-{
- SCM value;
- t_Conditions *cond;
-
- DebugCheck(!id);
- DebugCheck(!spellname);
- DebugCheck(!generic);
- DebugCheck(!specific);
-
- cond = malloc(sizeof(*cond));
- memset(cond, 0, sizeof(*cond));
- value = gh_car(list);
- if (!ccl_true(spellname, id, &cond->expectvalue, value)) {
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- if (!gh_eq_p(value, gh_symbol2scm("range"))) {
- DebugLevel0Fn("FIXME : WARNING : unknow flag");
- free(cond);
- return ;
- }
- list = gh_cdr(list);
- value = gh_car(list);
- cond->f.generic = CheckEnemyPresence; // In spell.c
- cond->u.range = gh_scm2int(value);
- if (cond->u.range <= 0 && cond->u.range != -1/*no limit*/) {
- DebugLevel0Fn("FIXME : WARNING : range <= 0");
- // Warn : range <= 0 have no sens, must be strict positive. or = -1
- free(cond);
- return ;
- }
- pushback_condition(generic, cond);
-}
-
/**
-** For enemy presence
-** list = #t
+** Get a condition value from a scm object.
+**
+** @param value scm value to convert.
+**
+** @return CONDITION_TRUE, CONDITION_FALSE, CONDITION_ONLY or -1 on error.
*/
-void ccl_alliance(const char *spellname, const char *id, SCM list,
- t_Conditions **generic, t_Conditions **specific)
+local char Scm2Condition(SCM value)
{
- SCM value;
- t_Conditions *cond;
-
- DebugCheck(!id);
- DebugCheck(!spellname);
- DebugCheck(!generic);
- DebugCheck(!specific);
-
- cond = malloc(sizeof(*cond));
- memset(cond, 0, sizeof(*cond));
- value = /*gh_car(*/list/*)*/;
- if (!ccl_true(spellname, id, &cond->expectvalue, value)) {// warn
user
- free(cond);
- return ;
+ if (gh_eq_p(value,gh_symbol2scm("true"))) {
+ return CONDITION_TRUE;
+ } else if (gh_eq_p(value,gh_symbol2scm("false"))) {
+ return CONDITION_FALSE;
+ } else if (gh_eq_p(value,gh_symbol2scm("only"))) {
+ return CONDITION_ONLY;
+ } else {
+ errl("Bad condition result",value);
+ return -1;
}
- cond->f.specific = CheckAllied;
- pushback_condition(specific, cond);
}
/**
** Parse the Condition for spell.
+**
+** @param list SCM object to parse
+** @param condition pointer to condition to fill with data.
+**
+** @notes: conditions must be allocated. All data already in is LOST.
*/
-local void ccl_spell_all_condition(const char *spellname, const char *id,
- SCM list, t_Conditions **generic, t_Conditions **specific)
+local void CclSpellParseCondition(SCM list, ConditionInfo* condition)
{
- int i;
- struct {
- const char *id;
- f_ccl_condition *f;
- } parser[] = {
- {"UnitTypeflag", ccl_UnitTypeFlag},
- {"DurationEffect", ccl_DurationEffect},
- {"Enemypresence", ccl_enemy_presence},
- {"Alliance", ccl_alliance},
- { NULL, 0}
- };
SCM value;
- DebugCheck(!id);
- DebugCheck(!spellname);
- DebugCheck(!generic);
- DebugCheck(!specific);
-
- for (; !gh_null_p(list); list = gh_cdr(list)) {
+ //
+ // Initializations:
+ //
+
+ // Set everything to 0:
+ memset(condition,0,sizeof(ConditionInfo));
+ // Flags are defaulted to 0(CONDITION_TRUE)
+
+ // Initialize min/max stuff to values with no effect.
+ condition->MinHpPercent=-10;
+ condition->MaxHpPercent=1000;
+ condition->MinManaPercent=-10;
+ condition->MaxManaPercent=1000;
+ // Buffs too.
+ condition->MaxHasteTicks=0xFFFFFFF;
+ condition->MaxSlowTicks=0xFFFFFFF;
+ condition->MaxBloodlustTicks=0xFFFFFFF;
+ condition->MaxInvisibilityTicks=0xFFFFFFF;
+ condition->MaxInvincibilityTicks=0xFFFFFFF;
+ // Now parse the list and set values.
+ while (!gh_null_p(list)) {
value = gh_car(list);
- for (i = 0; parser[i].id != NULL; i++) {
- if (gh_eq_p(value, gh_symbol2scm((char *) parser[i].id))) {
- list = gh_cdr(list);
- parser[i].f(spellname, parser[i].id, gh_car(list), generic,
specific);
- break;
- }
+ list = gh_cdr(list);
+ if (gh_eq_p(value,gh_symbol2scm("undead"))) {
+ condition->Undead=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("organic"))) {
+ condition->Organic=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("hero"))) {
+ condition->Hero=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("coward"))) {
+ condition->Coward=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("alliance"))) {
+ condition->Alliance=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("building"))) {
+ condition->Building=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("self"))) {
+ condition->TargetSelf=Scm2Condition(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("min-hp-percent"))) {
+ condition->MaxHpPercent=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-hp-percent"))) {
+ condition->MaxHpPercent=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("min-mana-percent"))) {
+ condition->MinManaPercent=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-mana-percent"))) {
+ condition->MaxManaPercent=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-slow-ticks"))) {
+ condition->MaxSlowTicks=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-haste-ticks"))) {
+ condition->MaxHasteTicks=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-bloodlust-ticks"))) {
+ condition->MaxBloodlustTicks=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-invisibility-ticks"))) {
+ condition->MaxInvisibilityTicks=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else if (gh_eq_p(value,gh_symbol2scm("max-invincibility-ticks"))) {
+ condition->MaxInvincibilityTicks=gh_scm2int(gh_car(list));
+ list=gh_cdr(list);
+ } else {
+ errl("Unsuported condition tag",value);
}
- DebugCheck(!parser[i].id);
}
}
/**
-** Parse the Condition for spell.
-*/
-local void ccl_spell_condition(const char *id, SCM list, SpellType *spell)
-{
- DebugCheck(!id);
- DebugCheck(!spell);
-
- ccl_spell_all_condition(spell->IdentName, id, list,
- &spell->Condition_generic,&spell->Condition_specific);
-}
-
-/**
** FIXME: docu
*/
local void ccl_spell_autocast(const char *id, SCM list, SpellType *spell)
@@ -658,8 +461,8 @@
}
list = gh_cdr(list);
value = gh_car(list);
- ccl_spell_all_condition(spell->IdentName, "Autocast conditions", value,
-
&spell->AutoCast->Condition_generic,&spell->AutoCast->Condition_specific);
+ spell->AutoCast->Condition=(ConditionInfo*)malloc(sizeof(ConditionInfo));
+ CclSpellParseCondition(value,spell->AutoCast->Condition);
}
/**
@@ -701,7 +504,11 @@
spell->ManaCost=gh_scm2int(gh_car(list));
list=gh_cdr(list);
} else if (gh_eq_p(value,gh_symbol2scm("range"))) {
- spell->Range=gh_scm2int(gh_car(list));
+ if (gh_eq_p(gh_car(list),gh_symbol2scm("infinite"))) {
+ spell->Range=INFINITE_RANGE;
+ } else {
+ spell->Range=gh_scm2int(gh_car(list));
+ }
list=gh_cdr(list);
} else if (gh_eq_p(value,gh_symbol2scm("target"))) {
value=gh_car(list);
@@ -710,7 +517,7 @@
} else if (gh_eq_p(value,gh_symbol2scm("self"))) {
spell->Target=TargetSelf;
} else if (gh_eq_p(value,gh_symbol2scm("unit"))) {
- spell->Target=TargetSelf;
+ spell->Target=TargetUnit;
} else if (gh_eq_p(value,gh_symbol2scm("position"))) {
spell->Target=TargetPosition;
} else {
@@ -722,7 +529,8 @@
CclParseSpellAction(gh_car(list),spell,spell->SpellAction);
list=gh_cdr(list);
} else if (gh_eq_p(value,gh_symbol2scm("condition"))) {
- ccl_spell_condition("condition",gh_car(list),spell);
+ spell->Conditions=(ConditionInfo*)malloc(sizeof(ConditionInfo));
+ CclSpellParseCondition(gh_car(list),spell->Conditions);
list=gh_cdr(list);
} else if (gh_eq_p(value,gh_symbol2scm("autocast"))) {
ccl_spell_autocast("autocast",gh_car(list),spell);
Index: stratagus/src/clone/spells.c
diff -u stratagus/src/clone/spells.c:1.102 stratagus/src/clone/spells.c:1.103
--- stratagus/src/clone/spells.c:1.102 Sat Sep 27 15:05:47 2003
+++ stratagus/src/clone/spells.c Mon Sep 29 13:04:14 2003
@@ -27,7 +27,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.c,v 1.102 2003/09/27 19:05:47 n0body Exp $
+// $Id: spells.c,v 1.103 2003/09/29 17:04:14 n0body Exp $
/*
** And when we cast our final spell
@@ -846,6 +846,7 @@
// target->TTL = GameCycle + CYCLES_PER_SECOND + CYCLES_PER_SECOND / 2;
target->CurrentSightRange = target->Stats->SightRange;
target->Removed = 1;
+ target->CurrentSightRange = target->Stats->SightRange;
MapMarkUnitSight(target);
target->TTL = GameCycle + target->Type->DecayRate * 6 * CYCLES_PER_SECOND;
CheckUnitToBeDrawn(target);
@@ -1038,21 +1039,31 @@
DebugCheck(!spell->SpellAction);
DebugCheck(!spell->SpellAction->Summon.UnitType);
+ DebugLevel0("Summoning\n");
ttl=spell->SpellAction->Summon.TTL;
caster->Mana -= spell->ManaCost;
// FIXME: johns: the unit is placed on the wrong position
target = MakeUnit(spell->SpellAction->Summon.UnitType, caster->Player);
target->X = x;
target->Y = y;
- DropOutOnSide(target, LookingW, 0, 0);
-
// set life span
if (ttl) {
target->TTL=GameCycle+ttl;
} else {
target->TTL=GameCycle+target->Type->DecayRate * 6 * CYCLES_PER_SECOND;
}
- CheckUnitToBeDrawn(target);
+ //
+ // Revealers are always removed, since they don't have graphics
+ //
+ if (target->Type->Revealer) {
+ DebugLevel0Fn("new unit is a revealer, removed.\n");
+ target->Removed=1;
+ target->CurrentSightRange = target->Stats->SightRange;
+ MapMarkUnitSight(target);
+ } else {
+ DropOutOnSide(target, LookingW, 0, 0);
+ CheckUnitToBeDrawn(target);
+ }
PlayGameSound(spell->SoundWhenCast.Sound,MaxSampleVolume);
MakeMissile(spell->Missile,
@@ -1095,137 +1106,6 @@
}
// ****************************************************************************
-// Specific conditions
-// ****************************************************************************
-
-/**
-** Check for unittype properties of unittype himself
-*/
-global int CheckUnitTypeFlag(const t_Conditions *condition,
- const Unit *caster, const Unit *target, int x, int y)
-{
- DebugCheck(!caster);
- DebugCheck(!condition);
-
- 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:
- DebugCheck(1);
- return !condition->expectvalue;
- }
-}
-
-/**
-** Check for alliance status.
-*/
-global int CheckAllied(const t_Conditions *condition, const Unit *caster,
- const Unit *target, int x, int y)
-{
- DebugCheck(!caster);
- return caster->Player == target->Player || IsAllied(caster->Player,
target) ? 1 : 0;
-}
-
-/**
-** Check if target is self
-*/
-global int CheckHimself(const t_Conditions *condition, const Unit *caster,
- const Unit *target, int x, int y)
-{
- DebugCheck(!caster);
- return caster == target;
-}
-
-/**
-** Check duration effects.
-*/
-global int CheckUnitDurationEffect(const t_Conditions *condition,
- const Unit *caster, const Unit *target, int x, int y)
-{
- int ttl;
-
- DebugCheck(!condition);
-
- ttl = condition->u.durationeffect.ttl;
-
- 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 : MaxMana.
- /// Add here the other cases
- default:
- DebugCheck(1);
- return !condition->expectvalue;
- }
-}
-
-// ****************************************************************************
-// Specific conditions
-// ****************************************************************************
-
-/**
-** FIXME: docu
-*/
-global int CheckEnemyPresence(const t_Conditions *condition, const Unit
*caster)
-{
- Unit *table[UnitMax];
- int i;
- int n;
- int range;
- int x;
- int y;
-
- DebugCheck(!condition);
- DebugCheck(!caster);
-
- range = condition->u.range;
- x = caster->X;
- y = caster->Y;
-
- // FIXME: +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;
- }
- }
- return 0;
-}
-
-// ****************************************************************************
// Target constructor
// ****************************************************************************
@@ -1281,61 +1161,98 @@
// Main local functions
// ****************************************************************************
-/**
-** Check all generic conditions.
+/*
+** Check the condition.
+**
+** @param caster Pointer to caster unit.
+** @param spell Pointer to the spell to cast.
+** @param target Pointer to target unit, or 0 if it is a
position spell.
+** @param x X position, or -1 if it is an unit spell.
+** @param y Y position, or -1 if it is an unit spell.
+** @param condition Pointer to condition info.
+**
+** @return 1 if passed, 0 otherwise.
*/
-local int PassGenericCondition(const Unit *caster, const SpellType *spell,
- const t_Conditions *condition)
+local int PassCondition(const Unit* caster,const SpellType* spell,const Unit*
target,
+ int x,int y,const ConditionInfo* condition)
{
- int ret;
-
- DebugCheck(!caster);
- DebugCheck(!spell);
-
- // FIXME : Move it in spell->Condition_generic ???
- // mana is a must!
- if (caster->Mana < spell->ManaCost) {
+ //
+ // Check caster mana. FIXME: move somewhere else?
+ //
+ if (caster->Mana<spell->ManaCost) {
+ return 0;
+ }
+ //
+ // Casting an unit spell without a target.
+ //
+ if (spell->Target==TargetUnit&&!target) {
return 0;
}
- /*condition = spell->Condition_generic*/
- for (; condition != NULL; condition = condition->next) {
- DebugCheck(!condition->f.generic);
- ret = condition->f.generic(condition, caster);
- DebugCheck(!(ret == 0 || ret == 1));
- DebugCheck(!(condition->expectvalue == 0 || condition->expectvalue ==
1));
- if (ret != condition->expectvalue) {
+ if (!condition) {
+ // no condition, pass.
+ return 1;
+ }
+ //
+ // Now check conditions regarding the target unit.
+ //
+ if (target) {
+ if (condition->Undead!=CONDITION_TRUE) {
+ if ((condition->Undead==CONDITION_ONLY)^(target->Type->IsUndead)) {
+ return 0;
+ }
+ }
+ if (condition->Organic!=CONDITION_TRUE) {
+ if ((condition->Organic==CONDITION_ONLY)^(target->Type->Organic)) {
+ return 0;
+ }
+ }
+ if (condition->Building!=CONDITION_TRUE) {
+ if ((condition->Building==CONDITION_ONLY)^(target->Type->Building))
{
+ DebugLevel0("QQQ\n");
+ return 0;
+ }
+ }
+ if (condition->Hero!=CONDITION_TRUE) {
+ if ((condition->Hero==CONDITION_ONLY)^(target->Type->Hero)) {
+ return 0;
+ }
+ }
+ if (condition->Coward!=CONDITION_TRUE) {
+ if ((condition->Coward==CONDITION_ONLY)^(target->Type->Coward)) {
+ return 0;
+ }
+ }
+ if (condition->Alliance!=CONDITION_TRUE) {
+ if
((condition->Alliance==CONDITION_ONLY)^(IsAllied(caster->Player,target))) {
+ return 0;
+ }
+ }
+ if (condition->TargetSelf!=CONDITION_TRUE) {
+ if ((condition->TargetSelf==CONDITION_ONLY)^(caster==target)) {
+ return 0;
+ }
+ }
+ //
+ // Check vitals now.
+ //
+ if (condition->MinHpPercent*target->Stats->HitPoints>target->HP) {
return 0;
}
- }
- return 1;
-}
-
-/**
-** Check all specific conditions.
-** @return 1 if condition is ok.
-** @return 0 else.
-*/
-local int PassSpecificCondition(const Unit *caster, const SpellType *spell,
- const Unit *target, int x, int y, const t_Conditions *condition)
-{
- int ret;
-
- DebugCheck(!caster);
- DebugCheck(!spell);
-
- for (/*condition = spell->Condition_specific*/; condition != NULL;
condition = condition->next) {
- DebugCheck(!condition->f.specific);
- ret = condition->f.specific(condition, caster, target, x, y);
- DebugCheck(!(ret == 0 || ret == 1));
- DebugCheck(!(condition->expectvalue == 0 || condition->expectvalue ==
1));
- if (ret != condition->expectvalue) {
+ if (condition->MaxHpPercent*target->Stats->HitPoints<target->HP) {
return 0;
}
+ if (target->Type->CanCastSpell) {
+ if (condition->MinManaPercent*target->Type->_MaxMana>target->Mana) {
+ return 0;
+ }
+ if (condition->MaxManaPercent*target->Type->_MaxMana<target->Mana) {
+ return 0;
+ }
+ }
}
return 1;
}
-
/**
** Select the target for the autocast.
**
@@ -1385,8 +1302,7 @@
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))
{
+ if (PassCondition(caster,spell,table[i],x,y,spell->Conditions))
{
table[j++] = table[i];
}
}
@@ -1572,8 +1488,7 @@
return 0;
}
- return PassGenericCondition(caster, spell, spell->Condition_generic)
- &&
PassSpecificCondition(caster,spell,target,x,y,spell->Condition_specific);
+ return PassCondition(caster,spell,target,x,y,spell->Conditions);
}
/**
@@ -1596,10 +1511,9 @@
target = NULL;
- if (!PassGenericCondition(caster, spell, spell->Condition_generic)
- || !PassGenericCondition(caster, spell,
spell->AutoCast->Condition_generic)) {
+/* if (PassCondition(caster,spell,target,x,y,spell->Conditions))
return 0;
- }
+ }*/
target = SelectTargetUnitsOfAutoCast(caster, spell);
if (target == NULL) {
return 0;
Index: stratagus/src/include/spells.h
diff -u stratagus/src/include/spells.h:1.25 stratagus/src/include/spells.h:1.26
--- stratagus/src/include/spells.h:1.25 Sat Sep 27 15:05:47 2003
+++ stratagus/src/include/spells.h Mon Sep 29 13:04:15 2003
@@ -26,7 +26,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
-// $Id: spells.h,v 1.25 2003/09/27 19:05:47 n0body Exp $
+// $Id: spells.h,v 1.26 2003/09/29 17:04:15 n0body Exp $
#ifndef __SPELLS_H__
#define __SPELLS_H__
@@ -187,46 +187,46 @@
*/
/**
-** Informations about the conditions of autocasting mode and simple cast.
+** Conditions for a spell.
**
** @todo Move more parameters into this structure.
*/
-struct s_Conditions;
-
-/*
-** Specific conditions.
-*/
-typedef int f_specific_condition(const struct s_Conditions *condition,
- const Unit* caster,const Unit* target,int x,int y);
-
-typedef int f_generic_condition(const struct s_Conditions
*condition,const Unit* caster);
-
-
-/**
-** Informations about the condition of autocasting mode.
-**
-** @todo Move more parameters into this structure.
-*/
-typedef struct s_Conditions {
- int expectvalue; /// Value expected (function
expected result, true or false)
- union {
- f_specific_condition *specific; /// Evaluation Function for the
condition.
- f_generic_condition *generic; /// Evaluation Function for the
condition.
- } f;
- union {
- int range; /// range
-// struct {
-// t_SpecificConditions c1;
-// t_SpecificConditions c2;
-// } or; //
- unsigned int flag; ///< flag
- struct {
- unsigned int flag;
- unsigned int ttl;
- } durationeffect; ///< durationeffect
- } u;
- struct s_Conditions *next; ///< for list.
-} t_Conditions;
+typedef struct ConditionInfo {
+ //
+ // Conditions that check specific flags. Possible values are the defines
below.
+ //
+#define CONDITION_FALSE 1
+#define CONDITION_TRUE 0
+#define CONDITION_ONLY 2
+ char Undead; /// Target is undead.
+ char Organic; /// Target is organic.
+ char Hero; /// Target is hero. Set this to false for
instant-kill spells.
+ char Coward; /// Target is coward. Don't bloodlust them.
+ char Alliance; /// Target is allied.
+ char Building; /// Target is a building.
+ char TargetSelf; /// Target is the same as the caster.
+ /// FIXME: NOT IMPLEMENTED:
+ char UnitBuffed; /// Target is buffed(haste/slow/bloodlust).
Dispel magic?
+ //
+ // Conditions related to vitals:
+ //
+ int MinHpPercent; /// Target must have more hp than that.
+ int MaxHpPercent; /// Target must have less hp than that. Used
for heal-like spells.
+ int MinManaPercent; /// Target must have more mana than
that. Mana drain spells?
+ int MaxManaPercent; /// Target must have less mana than
that. Mana fountains?
+ //
+ // Conditions related to buffs:
+ //
+ int MaxHasteTicks; /// Target must less haste ticks left.
+ int MaxSlowTicks; /// Target must less slow ticks left.
+ int MaxBloodlustTicks; /// Target must less bloodlust ticks left.
+ int MaxInvisibilityTicks; /// Target must less bloodlust ticks left.
+ int MaxInvincibilityTicks; /// Target must less bloodlust ticks left.
+ //
+ // FIXME: more? feel free to add, here and to
+ // FIXME: PassCondition, CclSpellParseCondition, SaveSpells
+ //
+} ConditionInfo;
/**
@@ -234,22 +234,18 @@
**
*/
typedef struct {
- t_Conditions *Condition_generic; ///< Conditions to cast
the spell. (generic (no test for each target))
- t_Conditions *Condition_specific; ///< Conditions to cast the
spell. (target specific (ex:Hp full))
-// Something to have a position target
- int Range;
/// Max range of the target.
-#if 0 // When sort supported
- t_f_order *f;
/// Sort functions for the best target.
-#endif
-} t_AutoCast;
+ ConditionInfo *Condition; /// Conditions to cast the spell.
+ int Range; /// Max range of the target.
+ /// FIXME: Add stuff here for target preference.
+ /// FIXME: Heal units with the lowest hit points first.
+} AutoCastInfo;
struct _spell_type_;
/*
** Pointer on function that cast the spell.
*/
-typedef int SpellFunc(Unit* caster, const struct _spell_type_* spell, Unit*
target,
- int x, int y);
+typedef int SpellFunc(Unit* caster, const struct _spell_type_* spell, Unit*
target,int x, int y);
/**
** Base structure of a spell type.
@@ -264,14 +260,15 @@
TargetType Target; /// Targetting information. See
TargetType.
SpellFunc *CastFunction; /// function to cast the spell.
SpellActionType *SpellAction; /// More arguments for spell (damage,
delay, additional sounds...).
+#define INFINITE_RANGE 0xFFFFFFF
int Range; /// Max range of the target.
int ManaCost; /// required mana for each cast
int DependencyId; /// Id of upgrade, -1 if no upgrade
needed for cast the spell.
- t_Conditions *Condition_generic; /// Conditions to cast the spell.
(generic (no test for each target))
- t_Conditions *Condition_specific; /// Conditions to cast the spell.
(target specific (ex:Hp full))
+ ConditionInfo *Conditions; /// Conditions to cast the spell.
(generic (no test for each target))
+
// Autocast // FIXME : can use different for AI ? Use it in this
structure ?
- t_AutoCast *AutoCast; /// AutoCast
information
+ AutoCastInfo *AutoCast; /// AutoCast information
// Uses for graphics and sounds
SoundConfig SoundWhenCast; /// sound played if cast
@@ -353,18 +350,6 @@
SpellFunc CastWhirlwind;
SpellFunc CastSpawnPortal;
-
-/*
-** generic condition.
-*/
-f_generic_condition CheckEnemyPresence;
-
-/*
-** Specific condition.
-*/
-f_specific_condition CheckUnitTypeFlag;
-f_specific_condition CheckAllied;
-f_specific_condition CheckUnitDurationEffect;
//@}