Applied jarod's flag patch.
This commit is contained in:
parent
8ca456c750
commit
7c28b39c7a
16 changed files with 325 additions and 174 deletions
|
@ -192,7 +192,6 @@ IFLAGS= -I$(TOPDIR)/src/include $(XIFLAGS) -I$(TOPDIR)/src/movie/vp31/include
|
|||
## There are some still not well tested code parts or branches.
|
||||
## UNIT_ON_MAP Fast lookup of units
|
||||
## UNITS_ON_MAP Faster lookup of units
|
||||
## NEW_AI New better improved AI code
|
||||
## USE_TILECACHE Faster tile drawing, costs memory.
|
||||
## USE_SMART_TILECACHE Faster tile drawing, slow with hardware video memory.
|
||||
## USE_HP_FOR_XP Use hit-points for XP calculations.
|
||||
|
@ -210,7 +209,7 @@ IFLAGS= -I$(TOPDIR)/src/include $(XIFLAGS) -I$(TOPDIR)/src/movie/vp31/include
|
|||
## HIERARCHIC_PATHFINDER Use hierarchic pathfinder
|
||||
## USE_LUA Lua scripting support
|
||||
DFLAGS= $(THREAD) $(CCL) $(VERSION) $(VIDEO) $(ZDEFS) $(DSOUND) $(DEBUG) \
|
||||
-DUNIT_ON_MAP -DNEW_AI -DUSE_FLAC -DUSE_OGG -DUSE_MAD \
|
||||
-DUNIT_ON_MAP -DUSE_FLAC -DUSE_OGG -DUSE_MAD \
|
||||
-DUSE_HP_FOR_XP # -DNEW_MAPDRAW=1 -DNEW_SHIPS
|
||||
|
||||
## choose optimise level
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
<li>Future 2.00 Release<p>
|
||||
<ul>
|
||||
<li>++
|
||||
<li>Applied patch #2116 (correct missile directions) (from Ludovic Jarod Dauphin).
|
||||
<li>Applied patch #2130 (missile flags and area-heal) (from Jarod Dauphin).
|
||||
<li>Applied patch #2116 (correct missile directions) (from Jarod Dauphin).
|
||||
<li>Added Neutral Minimap Color. (from Russell Smith).
|
||||
<li>Removed the demolish action, we now use the demolish spell. (from Crestez Leonard).
|
||||
<li>Applied patch #1969 (AI enhancement) (from Ludovic Pollet).
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<a href="ccl-index.html">Index</a>
|
||||
<hr>
|
||||
<a href="#define-animations">define-animations</a>
|
||||
<a href="#define-bool-flags">define-bool-flags</a>
|
||||
<a href="#define-unit-stats">define-unit-stats</a>
|
||||
<a href="#define-unit-type">define-unit-type</a>
|
||||
<a href="pud.html#define-unittype-wc-names">define-unittype-wc-names</a>
|
||||
|
@ -119,6 +120,20 @@ Define animations.
|
|||
#( 0 0 3 45) #( 0 0 3 50) #( 0 0 100 55) #( 3 0 1 55)))
|
||||
</pre>
|
||||
|
||||
<a name="define-bool-flags"></a>
|
||||
<h3>(define-bool-flags 'flag-1 'flag-2 ...)</h3>
|
||||
|
||||
Define boolean unit flags. Examples are organic, mechanical, undead, etc.
|
||||
Spells use these to determine who to hit, and units can be restricted too.
|
||||
Try to avoid using names with other meanings (nothing from unit definitions
|
||||
or spell condition definition.)
|
||||
|
||||
<h4>Example</h4>
|
||||
|
||||
<pre>
|
||||
(define-bool-flags 'organic 'hero 'mechanical 'undead 'demonic 'angelic)
|
||||
</pre>
|
||||
|
||||
<a name="define-unit-stats"></a>
|
||||
<h3>(define-unit-stats ident player 'tag1 value1 'tag2 value2 ...)</h3>
|
||||
|
||||
|
@ -415,12 +430,6 @@ be built on.
|
|||
<dd>This should be true for suicide bombers, a bit of a hack. Available as a
|
||||
target check for spells, making those invisible would ruin the game.
|
||||
</dd>
|
||||
<dt>organic</dt>
|
||||
<dd>This is a flag for spell target check.
|
||||
</dd>
|
||||
<dt>hero</dt>
|
||||
<dd>This is a flag for spell target check. Prevent instant kills for instance.
|
||||
</dd>
|
||||
<dt>coward</dt>
|
||||
<dd>Unit will not attack on sight, and will run away instead of retaliating.
|
||||
Use this for units that can't attack or are next to useless in combat (like
|
||||
|
@ -480,9 +489,6 @@ suicide. Doesn't work with resource workers/resources. It can even be used
|
|||
in combination with demolish-damage and demolish-range, though it wouldn't
|
||||
be very fair.
|
||||
</dd>
|
||||
<dt>sniper</dt>
|
||||
<dd>Unit can only target organic units.
|
||||
</dd>
|
||||
<dt>computer-reaction-range</dt>
|
||||
<dd>This is supossed to be the reaction range for AI units, but it is not used.
|
||||
</dd>
|
||||
|
@ -540,6 +546,17 @@ and can't be interacted with. Please see the documentation on spells.</dd>
|
|||
<dd>Most units should have this flag. When false the unit will only get selected
|
||||
alone, use this for buildings. Enemy units are never selectable by rectangle.
|
||||
</dd>
|
||||
<dt>flags<dt>
|
||||
<dd>You can add a bunch of flags, defined with <a href="#define-bool-flags">define-bool-flags</a>
|
||||
You can add how many flags you would like, but keep in mind that you have to call
|
||||
define-bool-flags before.
|
||||
</dd>
|
||||
<dt>can-target-flag</dt>
|
||||
<dd>This allows check for targetting similar to spell conditions. It has
|
||||
the following form: can-target-flag '(flag-1 true/false/only flag-2 true/false/only ... )
|
||||
By default everything is set to true, so you can target everything. Only means that
|
||||
you can only cast units with that flag, and false only units without that flag.
|
||||
</dd>
|
||||
<!--IDEA:<dt>force-minimap-color<dt>
|
||||
<dd>An unit with this flag will ignore any friend/foe/owning player considerations
|
||||
for the minimap color, and will force this. It takes a number from the palette here.
|
||||
|
|
3
setup
3
setup
|
@ -28,7 +28,7 @@
|
|||
##-----------------------------------------------------------------------------
|
||||
## HERE ARE SOME USER-CONFIGURABLE VARIABLES
|
||||
|
||||
EXTRA_CFLAGS="$CFLAGS -DUNIT_ON_MAP -DNEW_AI -DUSE_LIBMODPLUG -DUSE_HP_FOR_XP"
|
||||
EXTRA_CFLAGS="$CFLAGS -DUNIT_ON_MAP -DUSE_LIBMODPLUG -DUSE_HP_FOR_XP"
|
||||
EXTRA_LDFLAGS="$LDFLAGS"
|
||||
|
||||
## These could be used for experimental versions
|
||||
|
@ -41,7 +41,6 @@ EXTRA_LDFLAGS="$LDFLAGS"
|
|||
## There are some still not well tested code parts or branches.
|
||||
## UNIT_ON_MAP Fast lookup of units
|
||||
## UNITS_ON_MAP Faster lookup of units
|
||||
## NEW_AI New better improved AI code
|
||||
## USE_TILECACHE Faster tile drawing, costs memory.
|
||||
## USE_SMART_TILECACHE Faster tile drawing, slow with hardware video memory.
|
||||
## USE_HP_FOR_XP Use hit-points for XP calculations.
|
||||
|
|
|
@ -261,41 +261,6 @@ local void (*HandleActionTable[256])(Unit*) = {
|
|||
HandleActionNotWritten, HandleActionNotWritten, HandleActionNotWritten,
|
||||
};
|
||||
|
||||
/**
|
||||
** Do the runestone work each second.
|
||||
**
|
||||
** @param unit unit that heals an area
|
||||
*/
|
||||
local void IncrementAreaHealthMana(Unit* unit)
|
||||
{
|
||||
Unit* units[UnitMax];
|
||||
int nunits;
|
||||
int j;
|
||||
|
||||
// Get all the units around the unit
|
||||
nunits = SelectUnits(unit->X - unit->Stats->SightRange,
|
||||
unit->Y - unit->Stats->SightRange,
|
||||
unit->X + unit->Stats->SightRange+unit->Type->Width,
|
||||
unit->Y + unit->Stats->SightRange+unit->Type->Height,
|
||||
units);
|
||||
// Mana and HP on units, 2 every time
|
||||
for (j = 0; j < nunits; ++j) {
|
||||
if (units[j] == unit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Restore HP in everything but buildings (even in other player's units)
|
||||
if (units[j]->Type->Organic && units[j]->HP < units[j]->Stats->HitPoints) {
|
||||
units[j]->HP++;
|
||||
}
|
||||
|
||||
// Restore mana in all magical units
|
||||
if(units[j]->Type->CanCastSpell && units[j]->Mana < units[j]->Type->_MaxMana) {
|
||||
units[j]->Mana++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Increment a unit's health
|
||||
**
|
||||
|
@ -593,10 +558,6 @@ global void UnitActions(void)
|
|||
}
|
||||
}
|
||||
|
||||
//FIXME: Need to configure this to work
|
||||
if (0) { //Condition for Area Heal
|
||||
IncrementAreaHealthMana(unit);
|
||||
}
|
||||
if (healthiscycle) {
|
||||
IncrementUnitHealth(unit);
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ local char** ShownUnitTypes; /// Shown editor unit-type table
|
|||
local int MaxShownUnits; /// Max unit icon draw index
|
||||
local char ShowUnitsToSelect; /// Show units in unit list
|
||||
local char ShowBuildingsToSelect; /// Show buildings in unit list
|
||||
local char ShowHeroesToSelect; /// Show heroes in unit list
|
||||
//local char ShowHeroesToSelect; /// Show heroes in unit list
|
||||
local char ShowAirToSelect; /// Show air units in unit list
|
||||
local char ShowLandToSelect; /// Show land units in unit list
|
||||
local char ShowWaterToSelect; /// Show water units in unit list
|
||||
|
@ -376,9 +376,9 @@ local void RecalculateShownUnits(void)
|
|||
if (!type->Building && !ShowUnitsToSelect) {
|
||||
continue;
|
||||
}
|
||||
if (type->Hero && !ShowHeroesToSelect) {
|
||||
continue;
|
||||
}
|
||||
// if (type->Hero && !ShowHeroesToSelect) {
|
||||
// continue;
|
||||
// }
|
||||
if (type->UnitType == UnitTypeLand && !ShowLandToSelect) {
|
||||
continue;
|
||||
}
|
||||
|
@ -567,9 +567,9 @@ local void DrawUnitIcons(void)
|
|||
VideoDraw(MenuButtonGfx.Sprite,
|
||||
MBUTTON_GEM_SQUARE + (ShowBuildingsToSelect ? 2 : 0), x + 28 * 1,
|
||||
y + 16);
|
||||
VideoDrawText(x + 28 * 2, y, GameFont, "He");
|
||||
VideoDraw(MenuButtonGfx.Sprite,
|
||||
MBUTTON_GEM_SQUARE + (ShowHeroesToSelect ? 2 : 0), x + 28 * 2, y + 16);
|
||||
// VideoDrawText(x + 28 * 2, y, GameFont, "He");
|
||||
// VideoDraw(MenuButtonGfx.Sprite,
|
||||
// MBUTTON_GEM_SQUARE + (ShowHeroesToSelect ? 2 : 0), x + 28 * 2, y + 16);
|
||||
VideoDrawText(x + 28 * 3, y, GameFont, "La");
|
||||
VideoDraw(MenuButtonGfx.Sprite,
|
||||
MBUTTON_GEM_SQUARE + (ShowLandToSelect ? 2 : 0), x + 28 * 3, y + 16);
|
||||
|
@ -1162,14 +1162,14 @@ local void EditorCallbackButtonDown(unsigned button __attribute__ ((unused)))
|
|||
RecalculateShownUnits();
|
||||
return;
|
||||
}
|
||||
if (TheUI.InfoPanelX + 10 + 28 * 2 < CursorX &&
|
||||
CursorX < TheUI.InfoPanelX + 10 + 28 * 3 &&
|
||||
TheUI.InfoPanelY + 140 < CursorY &&
|
||||
CursorY < TheUI.InfoPanelY + 140 + 28) {
|
||||
ShowHeroesToSelect ^= 1;
|
||||
RecalculateShownUnits();
|
||||
return;
|
||||
}
|
||||
// if (TheUI.InfoPanelX + 10 + 28 * 2 < CursorX &&
|
||||
// CursorX < TheUI.InfoPanelX + 10 + 28 * 3 &&
|
||||
// TheUI.InfoPanelY + 140 < CursorY &&
|
||||
// CursorY < TheUI.InfoPanelY + 140 + 28) {
|
||||
// ShowHeroesToSelect ^= 1;
|
||||
// RecalculateShownUnits();
|
||||
// return;
|
||||
// }
|
||||
if (TheUI.InfoPanelX + 10 + 28 * 3 < CursorX &&
|
||||
CursorX < TheUI.InfoPanelX + 10 + 28 * 4 &&
|
||||
TheUI.InfoPanelY + 140 < CursorY &&
|
||||
|
@ -1924,7 +1924,7 @@ local void CreateEditor(void)
|
|||
|
||||
ShowUnitsToSelect = 1; // Show all units as default
|
||||
ShowBuildingsToSelect = 1;
|
||||
ShowHeroesToSelect = 1;
|
||||
// ShowHeroesToSelect = 1;
|
||||
ShowAirToSelect = 1;
|
||||
ShowLandToSelect = 1;
|
||||
ShowWaterToSelect = 1;
|
||||
|
|
|
@ -137,6 +137,7 @@ global void SaveGame(const char* filename)
|
|||
SaveConstructions(file);
|
||||
SaveDecorations(file);
|
||||
SaveMissileTypes(file);
|
||||
SaveFlags(file);
|
||||
SaveUnitTypeDefs(file);
|
||||
SaveSpells(file);
|
||||
SaveUnitTypes(file);
|
||||
|
|
|
@ -95,6 +95,11 @@ struct _spell_action_type_ {
|
|||
|
||||
// FIXME" some time information doesn't work as it should.
|
||||
union {
|
||||
struct {
|
||||
int HP; /// Target HP gain.(can be negative)
|
||||
int Mana; /// Target Mana gain.(can be negative)
|
||||
} AreaAdjustVitals;
|
||||
|
||||
struct {
|
||||
int Damage; /// Missile damage.
|
||||
int TTL; /// Missile TTL.
|
||||
|
@ -184,14 +189,12 @@ typedef struct ConditionInfo {
|
|||
#define CONDITION_FALSE 1
|
||||
#define CONDITION_TRUE 0
|
||||
#define CONDITION_ONLY 2
|
||||
char Undead; /// Target is undead.
|
||||
char Volatile; /// Target is volatile (suicide bomber).
|
||||
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.
|
||||
char *BoolFlag; /// User defined boolean flag.
|
||||
/// FIXME: NOT IMPLEMENTED:
|
||||
char UnitBuffed; /// Target is buffed(haste/slow/bloodlust). Dispel magic?
|
||||
//
|
||||
|
@ -218,7 +221,6 @@ typedef struct ConditionInfo {
|
|||
|
||||
/**
|
||||
** Informations about the autocasting mode.
|
||||
**
|
||||
*/
|
||||
typedef struct {
|
||||
/// FIXME: this below is SQUARE!!!
|
||||
|
@ -322,10 +324,14 @@ extern SpellType* SpellTypeById(int Id);
|
|||
|
||||
extern unsigned CclGetSpellByIdent(SCM value);
|
||||
|
||||
// return 0, 1, 2 for true, only, false.
|
||||
extern char Scm2Condition(SCM value);
|
||||
|
||||
/*
|
||||
** Spelltype to cast.
|
||||
*/
|
||||
|
||||
SpellFunc CastAreaAdjustVitals;
|
||||
SpellFunc CastAdjustVitals;
|
||||
SpellFunc CastAdjustBuffs;
|
||||
SpellFunc CastPolymorph;
|
||||
|
|
|
@ -293,16 +293,6 @@
|
|||
** If this is non-zero, then after that many clicks the unit will
|
||||
** commit suicide. Doesn't work with resource workers/resources.
|
||||
**
|
||||
** UnitType::Sniper
|
||||
**
|
||||
** This unit can only hit organic units.
|
||||
** TODO: have a table of armor types and damage types with damage
|
||||
** modifiers.
|
||||
**
|
||||
** UnitType::Wall
|
||||
**
|
||||
** This Unit is a wall, and should exihibit joining properties
|
||||
**
|
||||
** UnitType::Building
|
||||
**
|
||||
** Unit is a Building
|
||||
|
@ -375,10 +365,6 @@
|
|||
**
|
||||
** Can do command ground attack
|
||||
**
|
||||
** UnitType::IsUndead
|
||||
**
|
||||
** Unit is already dead
|
||||
**
|
||||
** UnitType::ShoreBuilding
|
||||
**
|
||||
** Building must be build on coast
|
||||
|
@ -413,20 +399,10 @@
|
|||
** Only valid for buildings without the BuilderOutside flag.
|
||||
** The worker is lost when the building is completed.
|
||||
**
|
||||
** UnitType::Hero
|
||||
**
|
||||
** FIXME: I don't think w*rcr*ft 2 exp heroes have this flag.
|
||||
** This is should be used for spells, to make heroes imune to
|
||||
** instant kill spells (like polymorph)
|
||||
**
|
||||
** UnitType::Volatile
|
||||
**
|
||||
** Unit is a suicide bomber
|
||||
**
|
||||
** UnitType::Organic
|
||||
**
|
||||
** Organic can be healed
|
||||
**
|
||||
** UnitType::SelectableByRectangle
|
||||
**
|
||||
** Selectable with mouse rectangle
|
||||
|
@ -740,8 +716,6 @@ struct _unit_type_ {
|
|||
unsigned AirUnit : 1; /// Air animated
|
||||
unsigned SeaUnit : 1; /// Sea animated
|
||||
unsigned ExplodeWhenKilled : 1; /// Death explosion animated
|
||||
unsigned Sniper : 1; /// The unit can only hit organic units.
|
||||
unsigned Wall : 1; /// Wall
|
||||
unsigned Building : 1; /// Building
|
||||
unsigned PermanentCloak : 1; /// Is only visible by CloakDetectors.
|
||||
unsigned DetectCloak : 1; /// Can see Cloaked units.
|
||||
|
@ -749,16 +723,15 @@ struct _unit_type_ {
|
|||
unsigned Transporter : 1; /// Can transport units
|
||||
unsigned Vanishes : 1; /// Corpes & destroyed places.
|
||||
unsigned GroundAttack : 1; /// Can do command ground attack.
|
||||
unsigned IsUndead : 1; /// Unit is already dead.
|
||||
unsigned ShoreBuilding : 1; /// Building must be build on coast.
|
||||
unsigned CanAttack : 1; /// Unit can attack.
|
||||
unsigned BuilderOutside : 1; /// The builder stays outside during the build.
|
||||
unsigned BuilderLost : 1; /// The builder is lost after the build.
|
||||
unsigned Hero : 1; /// Is hero only used for triggers .
|
||||
unsigned Volatile : 1; /// Unit is a suicide bomber.
|
||||
unsigned Organic : 1; /// Organic can be healed.
|
||||
unsigned CanHarvest : 1; /// Resource can be harvested.
|
||||
unsigned Harvester : 1; /// unit is a resource harvester.
|
||||
unsigned char *BoolFlag; /// User defined flag. Used for (dis)allow target.
|
||||
unsigned char *CanTargetFlag; /// Flag needed to target with missile.
|
||||
|
||||
unsigned SelectableByRectangle : 1; /// Selectable with mouse rectangle.
|
||||
unsigned Selectable : 1; /// Unit Is Selectable at all.
|
||||
|
@ -818,6 +791,9 @@ extern UnitType*UnitTypeOrcWall; /// Orc wall
|
|||
|
||||
extern char** UnitTypeWcNames; /// Mapping wc-number 2 symbol
|
||||
|
||||
extern char **BoolFlagName; /// Array of name of user defined bool flag.
|
||||
extern int NumberBoolFlag; /// Number of user defined bool flag.
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -832,6 +808,7 @@ extern UnitType* UnitTypeByWcNum(unsigned); /// Get unit-type by wc number
|
|||
/// Get the animations structure by ident
|
||||
extern Animations* AnimationsByIdent(const char* ident);
|
||||
|
||||
extern void SaveFlags(CLFile* file); /// Save declaration of user defined flas.
|
||||
extern void SaveUnitTypeDefs(CLFile* file); /// Declare the unit-type table first.
|
||||
extern void SaveUnitTypes(CLFile* file); /// Save the unit-type table
|
||||
extern UnitType* NewUnitTypeSlot(char*); /// Allocate an empty unit-type slot
|
||||
|
|
|
@ -1893,7 +1893,6 @@ global void MissileActionWhirlwind(Missile *missile)
|
|||
// Animate, move.
|
||||
//
|
||||
if (!missile->AnimWait--) {
|
||||
DebugLevel0Fn("?\n");
|
||||
if (NextMissileFrame(missile, 1, 0)) {
|
||||
missile->SpriteFrame = 0;
|
||||
PointToPointMissile(missile);
|
||||
|
@ -2018,12 +2017,12 @@ global void MissileActionDeathCoil(Missile *missile)
|
|||
// calculate organic enemy count
|
||||
for (i = 0; i < n; ++i) {
|
||||
ec += (IsEnemy(source->Player, table[i])
|
||||
&& table[i]->Type->Organic != 0);
|
||||
/*&& 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) {
|
||||
if (IsEnemy(source->Player, table[i])/* && table[i]->Type->Organic != 0*/) {
|
||||
// disperse damage between them
|
||||
//NOTE: 1 is the minimal damage
|
||||
HitUnit(source,table[i], missile->Damage / ec);
|
||||
|
|
|
@ -141,7 +141,21 @@ local void CclSpellAction(SCM list, SpellActionType* spellaction)
|
|||
errl("Unsupported area-bombardment tag", value);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("area-adjust-vitals"))) {
|
||||
spellaction->CastFunction = CastAreaAdjustVitals;
|
||||
while (!gh_null_p(list)) {
|
||||
value = gh_car(list);
|
||||
list = gh_cdr(list);
|
||||
if (gh_eq_p(value, gh_symbol2scm("hit-points"))) {
|
||||
spellaction->Data.AreaAdjustVitals.HP = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("mana-points"))) {
|
||||
spellaction->Data.AreaAdjustVitals.Mana = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else {
|
||||
errl("Unsupported area-adjust-vitals tag", value);
|
||||
}
|
||||
}
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("area-bombardment"))) {
|
||||
spellaction->CastFunction = CastAreaBombardment;
|
||||
while (!gh_null_p(list)) {
|
||||
|
@ -302,7 +316,7 @@ local void CclSpellAction(SCM list, SpellActionType* spellaction)
|
|||
** @note This is a helper function to make CclSpellCondition shorter
|
||||
** and easier to understand.
|
||||
*/
|
||||
local char Scm2Condition(SCM value)
|
||||
global char Scm2Condition(SCM value)
|
||||
{
|
||||
if (gh_eq_p(value, gh_symbol2scm("true"))) {
|
||||
return CONDITION_TRUE;
|
||||
|
@ -327,7 +341,7 @@ local char Scm2Condition(SCM value)
|
|||
local void CclSpellCondition(SCM list, ConditionInfo* condition)
|
||||
{
|
||||
SCM value;
|
||||
|
||||
int i;
|
||||
//
|
||||
// Initializations:
|
||||
//
|
||||
|
@ -335,7 +349,8 @@ local void CclSpellCondition(SCM list, ConditionInfo* condition)
|
|||
// Set everything to 0:
|
||||
memset(condition, 0, sizeof(ConditionInfo));
|
||||
// Flags are defaulted to 0(CONDITION_TRUE)
|
||||
|
||||
condition->BoolFlag = malloc(NumberBoolFlag * sizeof (*condition->BoolFlag));
|
||||
memset(condition->BoolFlag, 0, NumberBoolFlag * sizeof (*condition->BoolFlag));
|
||||
// Initialize min/max stuff to values with no effect.
|
||||
condition->MinHpPercent = -10;
|
||||
condition->MaxHpPercent = 1000;
|
||||
|
@ -351,18 +366,9 @@ local void CclSpellCondition(SCM list, ConditionInfo* condition)
|
|||
while (!gh_null_p(list)) {
|
||||
value = gh_car(list);
|
||||
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("volatile"))) {
|
||||
if (gh_eq_p(value, gh_symbol2scm("volatile"))) {
|
||||
condition->Volatile = 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);
|
||||
|
@ -403,6 +409,16 @@ local void CclSpellCondition(SCM list, ConditionInfo* condition)
|
|||
condition->MaxInvincibilityTicks = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else {
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
if (gh_eq_p(value, gh_symbol2scm(BoolFlagName[i]))) {
|
||||
condition->BoolFlag[i] = Scm2Condition(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NumberBoolFlag) {
|
||||
continue;
|
||||
}
|
||||
errl("Unsuported condition tag", value);
|
||||
}
|
||||
}
|
||||
|
@ -597,6 +613,15 @@ local void SaveSpellAction(CLFile *file,SpellActionType* action)
|
|||
action->Data.AreaBombardment.Damage,
|
||||
action->Data.AreaBombardment.StartOffsetX,
|
||||
action->Data.AreaBombardment.StartOffsetY);
|
||||
} else if (action->CastFunction == CastAreaAdjustVitals) {
|
||||
CLprintf(file, "(area-adjust-vitals");
|
||||
if (action->Data.AreaAdjustVitals.HP) {
|
||||
CLprintf(file, " hit-points %d", action->Data.AdjustVitals.HP);
|
||||
}
|
||||
if (action->Data.AreaAdjustVitals.Mana) {
|
||||
CLprintf(file, " mana-points %d", action->Data.AdjustVitals.Mana);
|
||||
}
|
||||
CLprintf(file, ")\n");
|
||||
} else if (action->CastFunction == CastSpawnMissile) {
|
||||
CLprintf(file, "(spawn-missile delay %d ttl %d damage %d ",
|
||||
action->Data.SpawnMissile.Delay,
|
||||
|
@ -691,7 +716,7 @@ local void SaveSpellCondition(CLFile *file, ConditionInfo* condition)
|
|||
"false", /// CONDITION_FALSE
|
||||
"only" /// CONDITION_ONLY
|
||||
};
|
||||
|
||||
int i;
|
||||
DebugCheck(!file);
|
||||
DebugCheck(!condition);
|
||||
|
||||
|
@ -700,18 +725,9 @@ local void SaveSpellCondition(CLFile *file, ConditionInfo* condition)
|
|||
// First save data related to flags.
|
||||
// NOTE: (int) is there to keep compilers happy.
|
||||
//
|
||||
if (condition->Undead != CONDITION_TRUE) {
|
||||
CLprintf(file, "undead %s ", condstrings[(int)condition->Undead]);
|
||||
}
|
||||
if (condition->Organic != CONDITION_TRUE) {
|
||||
CLprintf(file, "organic %s ", condstrings[(int)condition->Organic]);
|
||||
}
|
||||
if (condition->Volatile != CONDITION_TRUE) {
|
||||
CLprintf(file, "volatile %s ", condstrings[(int)condition->Volatile]);
|
||||
}
|
||||
if (condition->Hero != CONDITION_TRUE) {
|
||||
CLprintf(file, "hero %s ", condstrings[(int)condition->Hero]);
|
||||
}
|
||||
if (condition->Coward != CONDITION_TRUE) {
|
||||
CLprintf(file, "coward %s ", condstrings[(int)condition->Coward]);
|
||||
}
|
||||
|
@ -724,6 +740,12 @@ local void SaveSpellCondition(CLFile *file, ConditionInfo* condition)
|
|||
if (condition->TargetSelf != CONDITION_TRUE) {
|
||||
CLprintf(file, "self %s ", condstrings[(int)condition->TargetSelf]);
|
||||
}
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
if (condition->BoolFlag[i] != CONDITION_TRUE) {
|
||||
CLprintf(file, "%s %s ",
|
||||
BoolFlagName[i], condstrings[(int)condition->BoolFlag[i]]);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Min/Max vital percents
|
||||
//
|
||||
|
|
|
@ -209,6 +209,64 @@ global int CastSpawnPortal(Unit* caster, const SpellType* spell __attribute__((u
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Cast Area Adjust Vitals on all valid units in range.
|
||||
**
|
||||
** @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 CastAreaAdjustVitals(Unit* caster, const SpellType* spell,
|
||||
const SpellActionType* action, Unit* target __attribute__((unused)), int x, int y)
|
||||
{
|
||||
Unit* units[UnitMax];
|
||||
int nunits;
|
||||
int j;
|
||||
int hp;
|
||||
int mana;
|
||||
|
||||
DebugCheck(!caster);
|
||||
DebugCheck(!spell);
|
||||
DebugCheck(!action);
|
||||
// Get all the units around the unit
|
||||
nunits = SelectUnits(x - spell->Range,
|
||||
y - spell->Range,
|
||||
x + spell->Range + caster->Type->Width,
|
||||
y + spell->Range + caster->Type->Height,
|
||||
units);
|
||||
hp = action->Data.AreaAdjustVitals.HP;
|
||||
mana = action->Data.AreaAdjustVitals.Mana;
|
||||
caster->Mana -= spell->ManaCost;
|
||||
for (j = 0; j < nunits; ++j) {
|
||||
target = units[j];
|
||||
// if (!PassCondition(caster, spell, target, x, y) {
|
||||
if (!CanCastSpell(caster, spell, target, x, y)) {
|
||||
continue;
|
||||
}
|
||||
if (hp < 0) {
|
||||
HitUnit(caster, target, hp);
|
||||
} else {
|
||||
target->HP += hp;
|
||||
if (target->HP > target->Stats->HitPoints) {
|
||||
target->HP = target->Stats->HitPoints;
|
||||
}
|
||||
}
|
||||
target->Mana += mana;
|
||||
if (target->Mana < 0) {
|
||||
target->Mana = 0;
|
||||
}
|
||||
if (target->Mana > target->Type->_MaxMana) {
|
||||
target->Mana = target->Type->_MaxMana;
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
@ -697,6 +755,7 @@ local Target* NewTargetPosition(int x, int y)
|
|||
local int PassCondition(const Unit* caster, const SpellType* spell, const Unit* target,
|
||||
int x, int y, const ConditionInfo* condition)
|
||||
{
|
||||
int i;
|
||||
//
|
||||
// Check caster mana. FIXME: move somewhere else?
|
||||
//
|
||||
|
@ -717,16 +776,16 @@ local int PassCondition(const Unit* caster, const SpellType* spell, const Unit*
|
|||
// 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->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->Volatile != CONDITION_TRUE) {
|
||||
if ((condition->Volatile == CONDITION_ONLY) ^ (target->Type->Volatile)) {
|
||||
return 0;
|
||||
|
@ -737,16 +796,23 @@ local int PassCondition(const Unit* caster, const SpellType* spell, const Unit*
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
if (condition->Hero != CONDITION_TRUE) {
|
||||
if ((condition->Hero == CONDITION_ONLY) ^ (target->Type->Hero)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
if (condition->BoolFlag[i] != CONDITION_TRUE) {
|
||||
if ((condition->BoolFlag[i] == CONDITION_ONLY) ^ (target->Type->BoolFlag[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (condition->Alliance != CONDITION_TRUE) {
|
||||
if ((condition->Alliance == CONDITION_ONLY) ^
|
||||
(IsAllied(caster->Player,target) || target->Player == caster->Player)) {
|
||||
|
@ -1184,6 +1250,7 @@ void CleanSpells(void)
|
|||
free(spell->Name);
|
||||
free(spell->Action);
|
||||
if (spell->Condition) {
|
||||
free(spell->Condition->BoolFlag);
|
||||
free(spell->Condition);
|
||||
}
|
||||
//
|
||||
|
@ -1191,12 +1258,14 @@ void CleanSpells(void)
|
|||
//
|
||||
if (spell->AutoCast) {
|
||||
if (spell->AutoCast->Condition) {
|
||||
free(spell->AutoCast->Condition->BoolFlag);
|
||||
free(spell->AutoCast->Condition);
|
||||
}
|
||||
free(spell->AutoCast);
|
||||
}
|
||||
if (spell->AICast) {
|
||||
if (spell->AICast->Condition) {
|
||||
free(spell->AICast->Condition->BoolFlag);
|
||||
free(spell->AICast->Condition);
|
||||
}
|
||||
free(spell->AICast);
|
||||
|
|
|
@ -273,7 +273,11 @@ global void DoRightButton(int sx, int sy)
|
|||
DebugCheck(spellnum == SpellTypeCount);
|
||||
SendCommandSpellCast(unit, x, y, dest, spellnum, flush);
|
||||
} else {
|
||||
SendCommandAttack(unit, x, y, dest, flush);
|
||||
if (CanTarget(unit->Type, dest->Type)) {
|
||||
SendCommandAttack(unit, x, y, dest, flush);
|
||||
} else { // No valid target
|
||||
SendCommandAttack(unit, x, y, NoUnitP, flush);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,9 @@ global _AnimationsHash AnimationsHash; /// Animations hash table
|
|||
|
||||
local ccl_smob_type_t SiodUnitTypeTag; /// siod unit-type object
|
||||
|
||||
global char **BoolFlagName = NULL; /// Name of user defined flag
|
||||
global int NumberBoolFlag = 0; /// Number of defined flags.
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -128,6 +131,11 @@ local SCM CclDefineUnitType(SCM list)
|
|||
type->_RegenerationRate = 0;
|
||||
type->Selectable = 1;
|
||||
}
|
||||
type->BoolFlag = realloc(type->BoolFlag, NumberBoolFlag * sizeof (*type->BoolFlag));
|
||||
memset(type->BoolFlag, 0, NumberBoolFlag * sizeof (*type->BoolFlag));
|
||||
type->CanTargetFlag = realloc(type->CanTargetFlag, NumberBoolFlag * sizeof (*type->CanTargetFlag));
|
||||
memset(type->CanTargetFlag, 0, NumberBoolFlag * sizeof (*type->CanTargetFlag));
|
||||
|
||||
type->NumDirections = 8;
|
||||
|
||||
//
|
||||
|
@ -406,8 +414,6 @@ local SCM CclDefineUnitType(SCM list)
|
|||
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("building"))) {
|
||||
type->Building = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("wall"))) {
|
||||
type->Wall = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("builder-outside"))) {
|
||||
type->BuilderOutside = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("builder-lost"))) {
|
||||
|
@ -429,8 +435,6 @@ local SCM CclDefineUnitType(SCM list)
|
|||
} else if (gh_eq_p(value, gh_symbol2scm("clicks-to-explode"))) {
|
||||
type->ClicksToExplode = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("sniper"))) {
|
||||
type->Sniper = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("permanent-cloak"))) {
|
||||
type->PermanentCloak = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("detect-cloak"))) {
|
||||
|
@ -506,12 +510,8 @@ local SCM CclDefineUnitType(SCM list)
|
|||
}
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("vanishes"))) {
|
||||
type->Vanishes = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("hero"))) {
|
||||
type->Hero = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("volatile"))) {
|
||||
type->Volatile = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("isundead"))) {
|
||||
type->IsUndead = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("can-cast-spell"))) {
|
||||
//
|
||||
// Warning: can-cast-spell should only be used AFTER all spells
|
||||
|
@ -535,8 +535,29 @@ local SCM CclDefineUnitType(SCM list)
|
|||
sublist = gh_cdr(sublist);
|
||||
type->Magic = 1;
|
||||
}
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("organic"))) {
|
||||
type->Organic = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("can-target-flag"))) {
|
||||
//
|
||||
// Warning: can-target-flag should only be used AFTER all bool flags
|
||||
// have been defined.
|
||||
//
|
||||
sublist = gh_car(list);
|
||||
list = gh_cdr(list);
|
||||
while (!gh_null_p(sublist)) {
|
||||
value = gh_car(sublist);
|
||||
sublist = gh_cdr(sublist);
|
||||
for (i = 0; i < NumberBoolFlag; i++) {
|
||||
if (gh_eq_p(value, gh_symbol2scm(BoolFlagName[i]))) {
|
||||
type->CanTargetFlag[i] = Scm2Condition(gh_car(sublist));
|
||||
sublist = gh_cdr(sublist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NumberBoolFlag) {
|
||||
continue;
|
||||
}
|
||||
printf("\n%s\n", type->Name);
|
||||
errl("Unsupported flag tag for can-target-flag", value);
|
||||
}
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("selectable-by-rectangle"))) {
|
||||
type->SelectableByRectangle = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("teleporter"))) {
|
||||
|
@ -596,6 +617,15 @@ local SCM CclDefineUnitType(SCM list)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined bool flags
|
||||
if (gh_eq_p(value, gh_symbol2scm(BoolFlagName[i]))) {
|
||||
type->BoolFlag[i] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NumberBoolFlag) {
|
||||
continue;
|
||||
}
|
||||
// FIXME: this leaves a half initialized unit-type
|
||||
printf("\n%s\n",type->Name);
|
||||
errl("Unsupported tag", value);
|
||||
|
@ -978,7 +1008,7 @@ local SCM CclDefineAnimations(SCM list)
|
|||
if (anims->Attack) {
|
||||
free(anims->Attack);
|
||||
}
|
||||
anims->Attack=anim;
|
||||
anims->Attack = anim;
|
||||
} else if (gh_eq_p(id, gh_symbol2scm("die"))) {
|
||||
if (anims->Die) {
|
||||
free(anims->Die);
|
||||
|
@ -995,6 +1025,37 @@ local SCM CclDefineAnimations(SCM list)
|
|||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/*
|
||||
** Define boolean flag.
|
||||
**
|
||||
** @param list : list of flags' name.
|
||||
*/
|
||||
local SCM CclDefineBoolFlags(SCM list)
|
||||
{
|
||||
char* str;
|
||||
int i;
|
||||
|
||||
if (NumberBoolFlag != 0) {
|
||||
DebugLevel0("Warning, Redefine Bool flags\n");
|
||||
}
|
||||
while (!gh_null_p(list)) {
|
||||
str = gh_scm2newstr(gh_car(list), NULL);
|
||||
list = gh_cdr(list);
|
||||
for (i = 0; i < NumberBoolFlag; i++) {
|
||||
if (!strcmp(str, BoolFlagName[i])) {
|
||||
DebugLevel0("Warning, Bool flags already defined\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NumberBoolFlag) {
|
||||
break;
|
||||
}
|
||||
BoolFlagName = realloc(BoolFlagName, (NumberBoolFlag + 1) * sizeof (*BoolFlagName));
|
||||
BoolFlagName[NumberBoolFlag++] = str;
|
||||
}
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -1004,6 +1065,7 @@ global void UnitTypeCclRegister(void)
|
|||
{
|
||||
gh_new_procedureN("define-unit-type", CclDefineUnitType);
|
||||
gh_new_procedureN("define-unit-stats", CclDefineUnitStats);
|
||||
gh_new_procedureN("define-bool-flags", CclDefineBoolFlags);
|
||||
|
||||
SiodUnitTypeTag = CclMakeSmobType("UnitType");
|
||||
|
||||
|
|
|
@ -3311,9 +3311,14 @@ global int IsSharedVision(const Player* player, const Unit* dest)
|
|||
*/
|
||||
global int CanTarget(const UnitType* source, const UnitType* dest)
|
||||
{
|
||||
// Hack for snipers, can only target organic units.
|
||||
if (!dest->Organic && source->Sniper) {
|
||||
return 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NumberBoolFlag; i++) {
|
||||
if (source->CanTargetFlag[i] != CONDITION_TRUE) {
|
||||
if ((source->CanTargetFlag[i] == CONDITION_ONLY) ^ (dest->BoolFlag[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dest->UnitType == UnitTypeLand) {
|
||||
if (dest->ShoreBuilding) {
|
||||
|
|
|
@ -481,17 +481,17 @@ global void ParsePudUDTA(const char* udta, int length __attribute__((unused)))
|
|||
unittype->CanStore[GoldCost] = BIT(12, v);
|
||||
unittype->Vanishes = BIT(13, v);
|
||||
unittype->GroundAttack = BIT(14, v);
|
||||
unittype->IsUndead = BIT(15, v);
|
||||
// unittype->IsUndead = BIT(15, v);
|
||||
unittype->ShoreBuilding = BIT(16, v);
|
||||
// unittype->CanCastSpell = BIT(17,v);
|
||||
// unittype->CanCastSpell = (char*)malloc(/*nb_spell*/);
|
||||
unittype->CanCastSpell = NULL;//
|
||||
unittype->CanStore[WoodCost] = BIT(18, v);
|
||||
unittype->CanAttack = BIT(19, v);
|
||||
unittype->Hero = BIT(23, v);
|
||||
// unittype->Hero = BIT(23, v);
|
||||
unittype->CanStore[OilCost] = BIT(24, v);
|
||||
unittype->Volatile = BIT(25, v);
|
||||
unittype->Organic = BIT(27, v);
|
||||
// unittype->Organic = BIT(27, v);
|
||||
|
||||
if (BIT(11, v) || BIT(21, v)) {
|
||||
unittype->GivesResource = OilCost;
|
||||
|
@ -890,6 +890,14 @@ local void SaveUnitType(CLFile* file, const UnitType* type, int all)
|
|||
}
|
||||
CLprintf(file, "\n");
|
||||
}
|
||||
CLprintf(file, "'can-target-flag '(");
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
if (type->CanTargetFlag[i] != CONDITION_TRUE) {
|
||||
CLprintf(file, "%s %s ", BoolFlagName[i],
|
||||
type->CanTargetFlag[i] == CONDITION_ONLY ? "only" : "false");
|
||||
}
|
||||
}
|
||||
CLprintf(file, ") ");
|
||||
|
||||
if (type->Building) {
|
||||
CLprintf(file, " 'building");
|
||||
|
@ -923,9 +931,6 @@ local void SaveUnitType(CLFile* file, const UnitType* type, int all)
|
|||
if (type->ClicksToExplode) {
|
||||
CLprintf(file, " 'clicks-to-explode %d\n", type->ClicksToExplode);
|
||||
}
|
||||
if (type->Sniper) {
|
||||
CLprintf(file, " 'sniper \n");
|
||||
}
|
||||
if (type->Revealer) {
|
||||
CLprintf(file, " 'revealer\n");
|
||||
}
|
||||
|
@ -1034,24 +1039,20 @@ local void SaveUnitType(CLFile* file, const UnitType* type, int all)
|
|||
if (type->Vanishes) {
|
||||
CLprintf(file, " 'vanishes\n");
|
||||
}
|
||||
if (type->Hero) {
|
||||
CLprintf(file, " 'hero\n");
|
||||
}
|
||||
if (type->Volatile) {
|
||||
CLprintf(file, " 'volatile\n");
|
||||
}
|
||||
if (type->IsUndead) {
|
||||
CLprintf(file, " 'isundead\n");
|
||||
}
|
||||
if (type->Organic) {
|
||||
CLprintf(file, " 'organic\n");
|
||||
}
|
||||
if (type->SelectableByRectangle) {
|
||||
CLprintf(file, " 'selectable-by-rectangle\n");
|
||||
}
|
||||
if (type->Teleporter) {
|
||||
CLprintf(file, " 'teleporter\n");
|
||||
}
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
if (type->BoolFlag[i]) {
|
||||
CLprintf(file, " '%s\n", BoolFlagName[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CLprintf(file, " 'sounds '(");
|
||||
|
@ -1119,6 +1120,24 @@ local void SaveUnitStats(const UnitStats* stats,const char* ident,int plynr,
|
|||
CLprintf(file, ") )\n");
|
||||
}
|
||||
|
||||
/**
|
||||
** Save declaration of user defined flags.
|
||||
**
|
||||
** @param file Output file.
|
||||
*/
|
||||
global void SaveFlags(CLFile* file)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (NumberBoolFlag != 0) {
|
||||
CLprintf(file, "(define-bool-flags");
|
||||
for (i = 0; i < NumberBoolFlag; i++) {
|
||||
CLprintf(file, " '%s", BoolFlagName[i]);
|
||||
}
|
||||
CLprintf(file, ")\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Save the names of all unit types, before actually defining anything about them.
|
||||
**
|
||||
|
@ -1479,6 +1498,9 @@ global void CleanUnitTypes(void)
|
|||
DebugCheck(!type->Name);
|
||||
free(type->Name);
|
||||
|
||||
free(type->BoolFlag);
|
||||
free(type->CanTargetFlag);
|
||||
|
||||
if (type->SameSprite) {
|
||||
free(type->SameSprite);
|
||||
}
|
||||
|
@ -1563,6 +1585,13 @@ global void CleanUnitTypes(void)
|
|||
}
|
||||
NumUnitTypes = 0;
|
||||
|
||||
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
|
||||
free(BoolFlagName[i]);
|
||||
}
|
||||
free(BoolFlagName);
|
||||
BoolFlagName = NULL;
|
||||
NumberBoolFlag = 0;
|
||||
|
||||
//
|
||||
// Clean hardcoded unit types.
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue