Add DefineVariables (with associated stuff) and DefineDecorations

This commit is contained in:
jarod42 2004-05-29 15:50:41 +00:00
parent 44a9d3eb25
commit 5a29400daf
12 changed files with 1150 additions and 515 deletions

View file

@ -305,6 +305,7 @@ local void HandleRegenerations(Unit* unit)
local void HandleBuffs(Unit* unit, int amount)
{
int deadunit;
int i;
deadunit = 0;
//
@ -360,6 +361,18 @@ local void HandleBuffs(Unit* unit, int amount)
unit->UnholyArmor = 0;
}
}
// User defined variables
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
if (unit->Variable[i].Enable && unit->Variable[i].Increase) {
unit->Variable[i].Value += unit->Variable[i].Increase;
if (unit->Variable[i].Value <= 0) {
unit->Variable[i].Value = 0;
} else if (unit->Variable[i].Value > unit->Variable[i].Max) {
unit->Variable[i].Value = unit->Variable[i].Max;
}
}
}
}
/**

View file

@ -69,6 +69,8 @@
-- Functions
----------------------------------------------------------------------------*/
void InitDefinedVariables();
/**
** Cleanup modules.
**
@ -111,6 +113,7 @@ global void CleanModules(void)
MapSplitterClean();
#endif
FreeAStar();
InitDefinedVariables(); // internal script. should be to a better place, don't find for restart.
}
/**

View file

@ -136,6 +136,27 @@ struct _spell_action_type_ {
#define BUFF_NOT_AFFECTED 0xC0FF33 ///< Don't like the value? The value doesn't like you!
} AdjustBuffs;
struct {
int Index; ///< index of the variable to modify.
int Enable; ///< Value to affect to this field.
int Value; ///< Value to affect to this field.
int Max; ///< Value to affect to this field.
int Increase; ///< Value to affect to this field.
char ModifEnable; ///< true if we modify this field.
char ModifValue; ///< true if we modify this field.
char ModifMax; ///< true if we modify this field.
char ModifIncrease; ///< true if we modify this field.
char InvertEnable; ///< true if we invert this field.
int AddValue; ///< Add this value to this field.
int AddMax; ///< Add this value to this field.
int AddIncrease; ///< Add this value to this field.
int IncreaseTime; ///< How many time increase the Value field.
char TargetIsCaster; ///< true if the target is the caster.
} AdjustVariable;
struct {
int HP; ///< Target HP gain.(can be negative)
int Mana; ///< Target Mana gain.(can be negative)
@ -216,6 +237,19 @@ typedef struct ConditionInfo {
int MaxBloodlustTicks; ///< Target must less bloodlust ticks left.
int MaxInvisibilityTicks; ///< Target must less bloodlust ticks left.
int MaxInvincibilityTicks; ///< Target must less bloodlust ticks left.
struct {
char Enable; /// Target is 'user defined variable'.
int MinValue; /// Target must have more Value than that.
int MinMax; /// Target must have more Max than that.
int MinValuePercent; /// Target must have more (100 * Value / Max) than that.
int MaxValuePercent; /// Target must have less (100 * Value / Max) than that.
char ConditionApplyOnCaster; /// true if these condition are for caster.
// FIXME : More (increase, MaxValue, MaxMax) ?
} *Variable;
//
// @todo more? feel free to add, here and to
// @todo PassCondition, CclSpellParseCondition, SaveSpells
@ -335,6 +369,7 @@ extern char Ccl2Condition(lua_State* l, const char* value);
SpellFunc CastAreaAdjustVitals;
SpellFunc CastAdjustVitals;
SpellFunc CastAdjustBuffs;
SpellFunc CastAdjustVariable;
SpellFunc CastPolymorph;
SpellFunc CastAreaBombardment;
SpellFunc CastSummon;

View file

@ -568,6 +568,7 @@ struct _unit_ {
int HP; ///< hit points
int XP; ///< experience points
int Kills; ///< how many unit has this unit killed
VariableType *Variable; /// array of User Defined variables.
unsigned long TTL; ///< time to live
int Bloodlust; ///< ticks bloodlust
@ -706,15 +707,6 @@ extern int NumUnits; ///< Number of units used
// in unit_draw.c
/// @todo could be moved into the user interface ?
extern int ShowHealthBar; ///< Flag: show health bar
extern int ShowHealthDot; ///< Flag: show health dot
extern int ShowManaBar; ///< Flag: show mana bar
extern int ShowManaDot; ///< Flag: show mana dot
extern int ShowHealthHorizontal; ///< Flag: show health bar horizontal
extern int ShowManaHorizontal; ///< Flag: show mana bar horizontal
extern int ShowNoFull; ///< Flag: show no full health or mana
extern int ShowEnergySelectedOnly; ///< Flag: show energy only for selected
extern int DecorationOnTop; ///< Flag: show health and mana on top
extern int ShowSightRange; ///< Flag: show right range
extern int ShowReactionRange; ///< Flag: show reaction range
extern int ShowAttackRange; ///< Flag: show attack range

View file

@ -629,6 +629,84 @@ typedef struct _resource_info_ {
#endif
} ResourceInfo;
/**
** User defined variable type.
**
** It is used to define variables and use it after
** to manage magic, energy, shield or other stuff.
*/
typedef struct {
int Max; ///< Maximum for the variable. (Assume min is 0.)
int Value; ///< Current (or initial) value of the variable (or initial value).
char Increase; ///< Number to increase(decrease) Value by second.
char Enable; ///< True if the unit doesn't have this variable. (f.e shield)
} VariableType;
struct _decovartype_;
struct _unit_;
typedef void DrawDecoFunc(int x, int y, const struct _unit_* unit, const struct _decovartype_* Deco);
/**
** Decoration for userdefined variable.
**
** It is used to show variables graphicly.
** @todo add more stuff in this struct.
*/
typedef struct _decovartype_{
int Index; ///< Index of the variable. @see DefineVariables
int OffsetX; ///< Offset in X coord.
int OffsetY; ///< Offset in Y coord.
int OffsetXPercent; ///< Percent offset (TileWidth) in X coord.
int OffsetYPercent; ///< Percent offset (TileHeight) in Y coord.
char IsCenteredInX; ///< if true, use center of deco instead of left border
char IsCenteredInY; ///< if true, use center of deco instead of upper border
char ShowIfNotEnable; ///< if false, Show only if var is enable
char ShowWhenNull; ///< if false, don't show if var is null (F.E poison)
char HideHalf; ///< if true, don't show when 0 < var < max.
char ShowWhenMax; ///< if false, don't show if var is to max. (Like mana)
char ShowOnlySelected; ///< if true, show only for selected units.
char HideNeutral; ///< if true, don't show for neutral unit.
char HideAllied; ///< if true, don't show for allied unit. (but show own units)
char ShowOpponent; ///< if true, show for opponent unit.
DrawDecoFunc *f; ///< fonction to draw the decorations.
union {
struct {
char IsVertical; ///< if true, vertical bar, else horizontal.
char SEToNW; ///< (SouthEastToNorthWest), if false value 0 is on the left or up of the bar.
int Height; ///< Height of the bar.
int Width; ///< Width of the bar.
char ShowFullBackground; ///< if true, show background like value equal to max.
char BorderSize; ///< Size of the border, 0 for no border.
// FIXME color depend of percent (red, Orange, Yellow, Green...)
Uint32 Color; ///< Color of bar.
Uint32 BColor; ///< Color of background.
} Bar; ///< Use for Horizontal and vertical Bar.
struct {
// FIXME : Add Color, font, format
} Text;
struct {
char NSprite; ///< 0 for ManaSprite, 1 for HealthSprite.
// FIXME Sprite info. better way ?
} SpriteBar;
struct {
// FIXME Sprite info. and Replace n with more appropriate var.
int n; ///< identifiant in SpellSprite
} StaticSprite;
// FIXME : other method here.
} Data; ///< More Datas, depend of showing method
} DecoVarType;
/**
** Typedef of base structure of unit-type
*/
@ -744,6 +822,7 @@ struct _unit_type_ {
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.
VariableType *Variable; ///< Array of user defined variables.
unsigned char *CanTargetFlag; ///< Flag needed to target with missile.
unsigned SelectableByRectangle : 1; ///< Selectable with mouse rectangle.
@ -797,8 +876,18 @@ 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.
extern struct _UnitTypeVar_{
char **BoolFlagName; ///< Array of name of user defined bool flag.
int NumberBoolFlag; ///< Number of user defined bool flag.
char **VariableName; ///< Array of names of user defined variables.
VariableType *Variable; ///< Array of user defined variables (default value for unittype).
// EventType *Event; ///< Array of functions sets to call when en event occurs.
int NumberVariable; ///< Number of defined variables.
DecoVarType *DecoVar; ///< Array to describe how showing variable.
int NumberDeco; ///< Size of DecoVar.
} UnitTypeVar;
/*----------------------------------------------------------------------------
-- Functions
@ -812,6 +901,7 @@ extern void UpdateStats(int reset_to_default); ///< Update unit stats
extern void ParsePudUDTA(const char*,int); ///< Parse pud udta table
extern UnitType* UnitTypeByIdent(const char*); ///< Get unit-type by ident
extern UnitType* UnitTypeByWcNum(unsigned); ///< Get unit-type by wc number
extern int GetVariableIndex(const char *VarName); ///< Get index of the variable
/// Get the animations structure by ident
extern Animations* AnimationsByIdent(const char* ident);

View file

@ -263,6 +263,65 @@ local void CclSpellAction(lua_State* l, SpellActionType* spellaction)
LuaError(l, "Unsupported demolish tag: %s" _C_ value);
}
}
} else if (!strcmp(value, "adjust-variable")) {
spellaction->CastFunction = CastAdjustVariable;
spellaction->Data.AdjustVariable.Index = -1; // Invalid index
lua_rawgeti(l, -1, j + 1);
lua_pushnil(l);
Assert(lua_istable(l, -2));
while (lua_next(l, -2)) {
const char *key;
key = LuaToString(l, -2);
if (!strcmp(key, "Index")) {
int i;
value = LuaToString(l, -1);
spellaction->Data.AdjustVariable.Index = -1; // Invalid index
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
if (!strcmp(value, UnitTypeVar.VariableName[i])) {
spellaction->Data.AdjustVariable.Index = i;
}
}
} else if (!strcmp(key, "Enable")) {
spellaction->Data.AdjustVariable.Enable = LuaToBoolean(l, -1);
spellaction->Data.AdjustVariable.ModifEnable = 1;
} else if (!strcmp(key, "Value")) {
spellaction->Data.AdjustVariable.Value = LuaToNumber(l, -1);
spellaction->Data.AdjustVariable.ModifValue = 1;
} else if (!strcmp(key, "Max")) {
spellaction->Data.AdjustVariable.Max = LuaToNumber(l, -1);
spellaction->Data.AdjustVariable.ModifMax = 1;
} else if (!strcmp(key, "Increase")) {
spellaction->Data.AdjustVariable.Increase = LuaToNumber(l, -1);
spellaction->Data.AdjustVariable.ModifIncrease = 1;
} else if (!strcmp(key, "InvertEnable")) {
spellaction->Data.AdjustVariable.InvertEnable = LuaToBoolean(l, -1);
} else if (!strcmp(key, "AddValue")) {
spellaction->Data.AdjustVariable.AddValue = LuaToNumber(l, -1);
} else if (!strcmp(key, "AddMax")) {
spellaction->Data.AdjustVariable.AddMax = LuaToNumber(l, -1);
} else if (!strcmp(key, "AddIncrease")) {
spellaction->Data.AdjustVariable.AddIncrease = LuaToNumber(l, -1);
} else if (!strcmp(key, "IncreaseTime")) {
spellaction->Data.AdjustVariable.IncreaseTime = LuaToNumber(l, -1);
} else if (!strcmp(key, "TargetIsCaster")) {
value = LuaToString(l, -1);
if (!strcmp(value, "caster")) {
spellaction->Data.AdjustVariable.TargetIsCaster = 1;
} else if (!strcmp(value, "target")) {
spellaction->Data.AdjustVariable.TargetIsCaster = 0;
} else { // Error
lua_pushfstring(l, "key '%s' not valid for TargetIsCaster in adjustvariable", value);
lua_error(l);
}
} else { // Error
lua_pushfstring(l, "key '%s' not valid for adjustvariable", key);
lua_error(l);
}
lua_pop(l, 1); // Pop the value.
}
lua_pop(l, 1);
} else if (!strcmp(value, "adjust-buffs")) {
spellaction->CastFunction = CastAdjustBuffs;
spellaction->Data.AdjustBuffs.HasteTicks = BUFF_NOT_AFFECTED;
@ -456,7 +515,8 @@ local void CclSpellCondition(lua_State* l, ConditionInfo* condition)
// Set everything to 0:
memset(condition, 0, sizeof(ConditionInfo));
// Flags are defaulted to 0(CONDITION_TRUE)
condition->BoolFlag = calloc(NumberBoolFlag, sizeof (*condition->BoolFlag));
condition->BoolFlag = calloc(UnitTypeVar.NumberBoolFlag, sizeof (*condition->BoolFlag));
condition->Variable = calloc(UnitTypeVar.NumberVariable, sizeof (*condition->Variable));
// Initialize min/max stuff to values with no effect.
condition->MinHpPercent = -10;
condition->MaxHpPercent = 1000;
@ -468,6 +528,12 @@ local void CclSpellCondition(lua_State* l, ConditionInfo* condition)
condition->MaxBloodlustTicks = 0xFFFFFFF;
condition->MaxInvisibilityTicks = 0xFFFFFFF;
condition->MaxInvincibilityTicks = 0xFFFFFFF;
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
condition->Variable[i].MinValue = -1;
condition->Variable[i].MinMax = -1;
condition->Variable[i].MinValuePercent = -8;
condition->Variable[i].MaxValuePercent = 1024;
}
// Now parse the list and set values.
if (!lua_istable(l, -1)) {
LuaError(l, "incorrect argument");
@ -535,15 +601,54 @@ local void CclSpellCondition(lua_State* l, ConditionInfo* condition)
condition->MaxInvincibilityTicks = LuaToNumber(l, -1);
lua_pop(l, 1);
} else {
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
if (!strcmp(value, BoolFlagName[i])) {
for (i = 0; i < UnitTypeVar.NumberBoolFlag; i++) { // User defined flags
if (!strcmp(value, UnitTypeVar.BoolFlagName[i])) {
lua_rawgeti(l, -1, j + 1);
condition->BoolFlag[i] = Ccl2Condition(l, LuaToString(l, -1));
lua_pop(l, 1);
break;
}
}
if (i != NumberBoolFlag) {
if (i != UnitTypeVar.NumberBoolFlag) {
continue;
}
for (i = 0; i < UnitTypeVar.NumberVariable; i++) { // User defined flags
if (!strcmp(value, UnitTypeVar.VariableName[i])) {
lua_rawgeti(l, -1, j + 1);
if (lua_istable(l, -1)) {
lua_pushnil(l);
while (lua_next(l, -2)) {
const char *key;
key = LuaToString(l, -2);
if (!strcmp(key, "Enable")) {
condition->Variable[i].Enable = Ccl2Condition(l, LuaToString(l, -1));
} else if (!strcmp(key, "MinValue")) {
condition->Variable[i].MinValue = LuaToNumber(l, -1);
} else if (!strcmp(key, "MinMax")) {
condition->Variable[i].MinMax = LuaToNumber(l, -1);
} else if (!strcmp(key, "MinValuePercent")) {
condition->Variable[i].MinValuePercent = LuaToNumber(l, -1);
} else if (!strcmp(key, "MaxValuePercent")) {
condition->Variable[i].MaxValuePercent = LuaToNumber(l, -1);
} else if (!strcmp(key, "ConditionApplyOnCaster")) {
condition->Variable[i].ConditionApplyOnCaster = LuaToBoolean(l, -1);
} else { // Error
lua_pushfstring(l, "%s invalid for Variable in condition", key);
lua_error(l);
}
lua_pop(l, 1); // Pop value.
}
lua_pop(l, 1); // lua_rawgeti()
break;
} else { // Error
lua_pushstring(l, "Table expected in variable in condition");
lua_error(l);
}
lua_pop(l, 1); // lua_rawgeti()
}
}
if (i != UnitTypeVar.NumberVariable) {
continue;
}
LuaError(l, "Unsuported condition tag: %s" _C_ value);
@ -893,10 +998,10 @@ 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
for (i = 0; i < UnitTypeVar.NumberBoolFlag; i++) { // User defined flags
if (condition->BoolFlag[i] != CONDITION_TRUE) {
CLprintf(file, "%s %s ",
BoolFlagName[i], condstrings[(int)condition->BoolFlag[i]]);
UnitTypeVar.BoolFlagName[i], condstrings[(int)condition->BoolFlag[i]]);
}
}
//

View file

@ -450,6 +450,66 @@ global int CastAdjustBuffs(Unit* caster, const SpellType* spell,
return 0;
}
/**
** Adjust User Variables
**
** @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 CastAdjustVariable(Unit* caster, const SpellType* spell,
const SpellActionType* action, Unit* target, int x, int y)
{
int index;
Unit* unit;
Assert(action);
index = action->Data.AdjustVariable.Index;
Assert(0 <= index && index < UnitTypeVar.NumberVariable);
unit = (action->Data.AdjustVariable.TargetIsCaster) ? caster : target;
Assert(unit);
// Enable flag.
if (action->Data.AdjustVariable.ModifEnable) {
unit->Variable[index].Enable = action->Data.AdjustVariable.Enable;
}
unit->Variable[index].Enable ^= action->Data.AdjustVariable.InvertEnable;
// Max field
if (action->Data.AdjustVariable.ModifMax) {
unit->Variable[index].Max = action->Data.AdjustVariable.Max;
}
unit->Variable[index].Max += action->Data.AdjustVariable.AddMax;
// Increase field
if (action->Data.AdjustVariable.ModifIncrease) {
unit->Variable[index].Increase = action->Data.AdjustVariable.Increase;
}
unit->Variable[index].Increase += action->Data.AdjustVariable.AddIncrease;
// Value field
if (action->Data.AdjustVariable.ModifValue) {
unit->Variable[index].Value = action->Data.AdjustVariable.Value;
}
unit->Variable[index].Value += action->Data.AdjustVariable.AddValue;
unit->Variable[index].Value += action->Data.AdjustVariable.IncreaseTime
* unit->Variable[index].Increase;
if (unit->Variable[index].Value <= 0) {
unit->Variable[index].Value = 0;
} else if (unit->Variable[index].Value > unit->Variable[index].Max) {
unit->Variable[index].Value = unit->Variable[index].Max;
}
return 0;
}
/**
** Cast healing. (or exorcism)
**
@ -753,6 +813,36 @@ local int PassCondition(const Unit* caster, const SpellType* spell, const Unit*
if (!condition) { // no condition, pass.
return 1;
}
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
const Unit *unit;
unit = (condition->Variable[i].ConditionApplyOnCaster) ? caster : target;
Assert(unit);
if (condition->Variable[i].Enable != CONDITION_TRUE) {
if ((condition->Variable[i].Enable == CONDITION_ONLY) ^ (unit->Variable[i].Enable)) {
return 0;
}
}
// Value and Max
if (condition->Variable[i].MinValue >= unit->Variable[i].Value) {
return 0;
}
if (condition->Variable[i].MinMax >= unit->Variable[i].Max) {
return 0;
}
// Percent
if (condition->Variable[i].MinValuePercent * unit->Variable[i].Max
> 100 * unit->Variable[i].Value) {
return 0;
}
if (condition->Variable[i].MaxValuePercent * unit->Variable[i].Max
< 100 * unit->Variable[i].Value) {
return 0;
}
}
if (!target) {
return 1;
}
@ -766,7 +856,7 @@ local int PassCondition(const Unit* caster, const SpellType* spell, const Unit*
return 0;
}
}
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
for (i = 0; i < UnitTypeVar.NumberBoolFlag; i++) { // User defined flags
if (condition->BoolFlag[i] != CONDITION_TRUE) {
if ((condition->BoolFlag[i] == CONDITION_ONLY) ^ (target->Type->BoolFlag[i])) {
return 0;

View file

@ -58,6 +58,8 @@
/// Get resource by name
extern unsigned CclGetResourceByName(lua_State* l);
/// Parse User Variables field.
extern void DefineVariableField(lua_State *l, int var_index, int lua_index);
/**
** Set xp damage
@ -915,6 +917,11 @@ local int CclUnit(lua_State* l)
}
unit->AutoCastSpell[SpellTypeByIdent(s)->Slot] = 1;
} else {
i = GetVariableIndex(value); // User variables
if (i != -1) { // Valid index
DefineVariableField(l, i, j + 1);
continue;
}
// FIXME: this leaves a half initialized unit
LuaError(l, "Unsupported tag: %s" _C_ value);
}

View file

@ -60,13 +60,19 @@ extern int NoWarningUnitType; /// quiet ident lookup.
global _AnimationsHash AnimationsHash; /// Animations hash table
global char** BoolFlagName; /// Name of user defined flag
global int NumberBoolFlag; /// Number of defined flags.
global struct _UnitTypeVar_ UnitTypeVar;
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
void DefineVariableField(lua_State *l, int var_index, int lua_index);
DrawDecoFunc DrawBar;
DrawDecoFunc PrintValue;
DrawDecoFunc DrawSpriteBar;
DrawDecoFunc DrawStaticSprite;
/**
** Get the resource ID from a SCM object.
**
@ -126,8 +132,11 @@ local int CclDefineUnitType(lua_State* l)
redefine = 1;
} else {
type = NewUnitTypeSlot(str);
type->BoolFlag = calloc(NumberBoolFlag, sizeof(*type->BoolFlag));
type->CanTargetFlag = calloc(NumberBoolFlag, sizeof(*type->CanTargetFlag));
type->BoolFlag = calloc(UnitTypeVar.NumberBoolFlag, sizeof(*type->BoolFlag));
type->CanTargetFlag = calloc(UnitTypeVar.NumberBoolFlag, sizeof(*type->CanTargetFlag));
type->Variable = calloc(UnitTypeVar.NumberVariable, sizeof(*type->Variable));
memcpy(type->Variable, UnitTypeVar.Variable,
UnitTypeVar.NumberVariable * sizeof(*type->Variable));
redefine = 0;
}
@ -670,8 +679,8 @@ local int CclDefineUnitType(lua_State* l)
value = LuaToString(l, -1);
lua_pop(l, 1);
++k;
for (i = 0; i < NumberBoolFlag; ++i) {
if (!strcmp(value, BoolFlagName[i])) {
for (i = 0; i < UnitTypeVar.NumberBoolFlag; ++i) {
if (!strcmp(value, UnitTypeVar.BoolFlagName[i])) {
lua_rawgeti(l, -1, k + 1);
value = LuaToString(l, -1);
lua_pop(l, 1);
@ -679,7 +688,7 @@ local int CclDefineUnitType(lua_State* l)
break;
}
}
if (i != NumberBoolFlag) {
if (i != UnitTypeVar.NumberBoolFlag) {
continue;
}
printf("\n%s\n", type->Name);
@ -776,13 +785,30 @@ local int CclDefineUnitType(lua_State* l)
}
}
} else {
for (i = 0; i < NumberBoolFlag; ++i) { // User defined bool flags
if (!strcmp(value, BoolFlagName[i])) {
i = GetVariableIndex(value);
if (i != -1) { // valid index
if (lua_isboolean(l, -1)) {
type->Variable[i].Enable = LuaToBoolean(l, -1);
} else if (lua_istable(l, -1)) {
DefineVariableField(l, i, -1);
} else if (lua_isnumber(l, -1)) {
type->Variable[i].Enable = 1;
type->Variable[i].Value = LuaToNumber(l, -1);
type->Variable[i].Max = LuaToNumber(l, -1);
} else { // Error
lua_pushstring(l, "incorrect argument for the variable in unittype");
lua_error(l);
}
lua_pop(l, 1);
continue;
}
for (i = 0; i < UnitTypeVar.NumberBoolFlag; ++i) { // User defined bool flags
if (!strcmp(value, UnitTypeVar.BoolFlagName[i])) {
type->BoolFlag[i] = LuaToBoolean(l, -1);
break;
}
}
if (i == NumberBoolFlag) {
if (i == UnitTypeVar.NumberBoolFlag) {
printf("\n%s\n",type->Name);
LuaError(l, "Unsupported tag: %s" _C_ value);
}
@ -1187,6 +1213,102 @@ local int CclDefineAnimations(lua_State* l)
return 0;
}
/**
** Define the field of the UserDefined variables
**
** @param l lua_state.
** @param var_index index of variable to set.
** @param var_index index of the table where are the infos
**
** @internal Use to not duplicate code.
*/
global void DefineVariableField(lua_State *l, int var_index, int lua_index)
{
if (lua_index < 0) { // relative index
lua_index--;
}
lua_pushnil(l);
while(lua_next(l, lua_index)) {
const char *key;
key = LuaToString(l, -2);
if (!strcmp(key, "Value")) {
UnitTypeVar.Variable[var_index].Value = LuaToNumber(l, -1);
} else if (!strcmp(key, "Max")) {
UnitTypeVar.Variable[var_index].Max = LuaToNumber(l, -1);
} else if (!strcmp(key, "Increase")) {
UnitTypeVar.Variable[var_index].Increase = LuaToNumber(l, -1);
} else if (!strcmp(key, "Enable")) {
UnitTypeVar.Variable[var_index].Enable = LuaToBoolean(l, -1);
} else { // Error.
lua_pushfstring(l, "incorrect field '%s' for the variable '%s'",
key, UnitTypeVar.VariableName[var_index]);
lua_error(l);
}
lua_pop(l, 1); // pop the value;
}
}
/**
** return the index of the variable named VarName.
**
** @param VarName name of the variable
**
** @return index of the variable.
*/
global int GetVariableIndex(const char *VarName)
{
int i;
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
if (!strcmp(VarName, UnitTypeVar.VariableName[i])) {
return i;
}
}
DebugPrint("Unknow variable \"%s\", use DefineVariables() before." _C_ VarName);
return -1;
}
/**
** Define user variables.
**
** @param l :
** @return 0.
*/
local int CclDefineVariables(lua_State* l)
{
const char *str;
int i;
int args;
int j;
args = lua_gettop(l);
for (j = 0; j < args; ++j) {
str = LuaToString(l, j + 1);
for (i = 0; i < UnitTypeVar.NumberVariable; ++i) {
if (!strcmp(str, UnitTypeVar.VariableName[i])) {
DebugPrint("Warning, User Variable \"%s\" redefined\n" _C_ str);
break;
}
}
if (i == UnitTypeVar.NumberVariable) { // new variable.
UnitTypeVar.VariableName = realloc(UnitTypeVar.VariableName,
(i + 1) * sizeof(*UnitTypeVar.VariableName));
UnitTypeVar.VariableName[i] = strdup(str);
UnitTypeVar.Variable = realloc(UnitTypeVar.Variable,
(i + 1) * sizeof(*UnitTypeVar.Variable));
memset(UnitTypeVar.Variable + i, 0, sizeof (*UnitTypeVar.Variable));
UnitTypeVar.NumberVariable++;
}
if (!lua_istable(l, j + 2)) { // No change => default value.
continue;
}
j++;
DefineVariableField(l, i, j + 1);
}
return 0;
}
/**
** Define boolean flag.
**
@ -1200,40 +1322,205 @@ local int CclDefineBoolFlags(lua_State* l)
int j;
int old;
old = NumberBoolFlag;
old = UnitTypeVar.NumberBoolFlag;
args = lua_gettop(l);
for (j = 0; j < args; ++j) {
str = LuaToString(l, j + 1);
for (i = 0; i < NumberBoolFlag; ++i) {
if (!strcmp(str, BoolFlagName[i])) {
for (i = 0; i < UnitTypeVar.NumberBoolFlag; ++i) {
if (!strcmp(str, UnitTypeVar.BoolFlagName[i])) {
DebugPrint("Warning, Bool flags already defined\n");
break;
}
}
if (i != NumberBoolFlag) {
DebugPrint("Warning, Bool flags '%s' already defined\n" _C_ BoolFlagName[i]);
if (i != UnitTypeVar.NumberBoolFlag) {
DebugPrint("Warning, Bool flags '%s' already defined\n" _C_ UnitTypeVar.BoolFlagName[i]);
continue;
}
BoolFlagName = realloc(BoolFlagName, (NumberBoolFlag + 1) * sizeof(*BoolFlagName));
BoolFlagName[NumberBoolFlag++] = strdup(str);
UnitTypeVar.BoolFlagName = realloc(UnitTypeVar.BoolFlagName,
(UnitTypeVar.NumberBoolFlag + 1) * sizeof(*UnitTypeVar.BoolFlagName));
UnitTypeVar.BoolFlagName[UnitTypeVar.NumberBoolFlag++] = strdup(str);
}
if (0 < old && old != NumberBoolFlag) {
if (0 < old && old != UnitTypeVar.NumberBoolFlag) {
for (i = 0; i < NumUnitTypes; i++) { // adjust array for unit already defined
UnitTypes[i]->BoolFlag = realloc(UnitTypes[i]->BoolFlag,
NumberBoolFlag * sizeof((*UnitTypes)->BoolFlag));
UnitTypeVar.NumberBoolFlag * sizeof((*UnitTypes)->BoolFlag));
UnitTypes[i]->CanTargetFlag = realloc(UnitTypes[i]->CanTargetFlag,
NumberBoolFlag * sizeof((*UnitTypes)->CanTargetFlag));
UnitTypeVar.NumberBoolFlag * sizeof((*UnitTypes)->CanTargetFlag));
memset(UnitTypes[i]->BoolFlag + old, 0,
(NumberBoolFlag - old) * sizeof((*UnitTypes)->BoolFlag));
(UnitTypeVar.NumberBoolFlag - old) * sizeof((*UnitTypes)->BoolFlag));
memset(UnitTypes[i]->CanTargetFlag + old, 0,
(NumberBoolFlag - old) * sizeof((*UnitTypes)->CanTargetFlag));
(UnitTypeVar.NumberBoolFlag - old) * sizeof((*UnitTypes)->CanTargetFlag));
}
}
return 0;
}
/**
** Define Decorations for user variables
**
** @param list : lua_state.
** @return 0;
** @todo modify Assert with luastate with User Error.
** @todo continue to add configuration.
*/
local int CclDefineDecorations(lua_State* l)
{
int i;
int nargs;
int j;
const char *key;
DecoVarType DecoVar;
nargs = lua_gettop(l);
for (i = 0; i < nargs; i++) {
Assert(lua_istable(l, i + 1));
memset(&DecoVar, 0, sizeof(DecoVar));
lua_pushnil(l);
while (lua_next(l, i + 1)) {
key = LuaToString(l, -2);
if (!strcmp(key, "Index")) {
DecoVar.Index = GetVariableIndex(LuaToString(l, -1));
} else if (!strcmp(key, "Offset")) {
Assert(lua_istable(l, -1));
lua_rawgeti(l, -1, 1); // X
lua_rawgeti(l, -2, 2); // Y
DecoVar.OffsetX = LuaToNumber(l, -2);
DecoVar.OffsetY = LuaToNumber(l, -1);
lua_pop(l, 2); // Pop X and Y
} else if (!strcmp(key, "OffsetPercent")) {
Assert(lua_istable(l, -1));
lua_rawgeti(l, -1, 1); // X
lua_rawgeti(l, -2, 2); // Y
DecoVar.OffsetXPercent = LuaToNumber(l, -2);
DecoVar.OffsetYPercent = LuaToNumber(l, -1);
lua_pop(l, 2); // Pop X and Y
} else if (!strcmp(key, "CenterX")) {
DecoVar.IsCenteredInX = LuaToBoolean(l, -1);
} else if (!strcmp(key, "CenterY")) {
DecoVar.IsCenteredInY = LuaToBoolean(l, -1);
} else if (!strcmp(key, "ShowIfNotEnable")) {
DecoVar.ShowIfNotEnable = LuaToBoolean(l, -1);
} else if (!strcmp(key, "ShowWhenNull")) {
DecoVar.ShowWhenNull = LuaToBoolean(l, -1);
} else if (!strcmp(key, "HideHalf")) {
DecoVar.HideHalf = LuaToBoolean(l, -1);
} else if (!strcmp(key, "ShowWhenMax")) {
DecoVar.ShowWhenMax = LuaToBoolean(l, -1);
} else if (!strcmp(key, "ShowOnlySelected")) {
DecoVar.ShowOnlySelected = LuaToBoolean(l, -1);
} else if (!strcmp(key, "HideNeutral")) {
DecoVar.HideNeutral = LuaToBoolean(l, -1);
} else if (!strcmp(key, "HideAllied")) {
DecoVar.HideAllied = LuaToBoolean(l, -1);
} else if (!strcmp(key, "ShowOpponent")) {
DecoVar.ShowOpponent = LuaToBoolean(l, -1);
} else if (!strcmp(key, "Method")) {
Assert(lua_istable(l, -1));
lua_rawgeti(l, -1, 1); // MethodName
lua_rawgeti(l, -2, 2); // Data
Assert(lua_istable(l, -1));
key = LuaToString(l, -2);
if (!strcmp(key, "bar")) {
DecoVar.f = DrawBar;
lua_pushnil(l);
while (lua_next(l, -2)) {
key = LuaToString(l, -2);
if (!strcmp(key, "Height")) {
DecoVar.Data.Bar.Height = LuaToNumber(l, -1);
} else if (!strcmp(key, "Width")) {
DecoVar.Data.Bar.Width = LuaToNumber(l, -1);
} else if (!strcmp(key, "Orientation")) {
key = LuaToString(l, -1);;
if (!strcmp(key, "horizontal")) {
DecoVar.Data.Bar.IsVertical = 0;
} else if (!strcmp(key, "vertical")) {
DecoVar.Data.Bar.IsVertical = 1;
} else { // Error
lua_pushfstring(l, "invalid Orientation '%s' for bar in DefineDecorations", key);
lua_error(l);
}
} else if (!strcmp(key, "SEToNW")) {
DecoVar.Data.Bar.SEToNW = LuaToBoolean(l, -1);
} else if (!strcmp(key, "BorderSize")) {
DecoVar.Data.Bar.BorderSize = LuaToNumber(l, -1);
} else if (!strcmp(key, "ShowFullBackground")) {
DecoVar.Data.Bar.ShowFullBackground = LuaToBoolean(l, -1);
#if 0 // FIXME Color configuration
} else if (!strcmp(key, "Color")) {
DecoVar.Data.Bar.Color = // FIXME
} else if (!strcmp(key, "BColor")) {
DecoVar.Data.Bar.BColor = // FIXME
#endif
} else {
lua_pushfstring(l, "'%s' invalid for Method bar", key);
lua_error(l);
}
lua_pop(l, 1); // Pop value
}
} else if (!strcmp(key, "text")) {
DecoVar.f = PrintValue;
// FIXME : More arguments ? Font, color...
} else if (!strcmp(key, "sprite")) {
DecoVar.f = DrawSpriteBar;
lua_rawgeti(l, -1, 1);
DecoVar.Data.SpriteBar.NSprite = LuaToNumber(l, -1);
lua_pop(l, 1);
// FIXME : More arguments ?
} else if (!strcmp(key, "static-sprite")) {
DecoVar.f = DrawStaticSprite;
lua_rawgeti(l, -1, 1);
DecoVar.Data.StaticSprite.n = LuaToNumber(l, -1);
lua_pop(l, 1);
} else { // Error
lua_pushfstring(l, "invalid method '%s' for Method in DefineDecorations", key);
lua_error(l);
}
lua_pop(l, 2); // MethodName and data
} else { // Error
lua_pushfstring(l, "invalid key '%s' for DefineDecorations", key);
lua_error(l);
}
lua_pop(l, 1); // Pop the value
}
for (j = 0; j < UnitTypeVar.NumberDeco; j++) {
if (DecoVar.Index == UnitTypeVar.DecoVar[j].Index) {
break;
}
}
if (j == UnitTypeVar.NumberDeco) {
UnitTypeVar.NumberDeco++;
UnitTypeVar.DecoVar = realloc(UnitTypeVar.DecoVar,
UnitTypeVar.NumberDeco * sizeof (*UnitTypeVar.DecoVar));
}
UnitTypeVar.DecoVar[j] = DecoVar;
}
Assert(lua_gettop(l));
return 0;
}
// ----------------------------------------------------------------------------
/**
** Define already variables, usefull for drawing now.
*/
global void InitDefinedVariables()
{
#define NVARALREADYDEFINED 7
const char *var[NVARALREADYDEFINED] = {"HitPoints", "Mana", "Transport",
"Research", "Training", "UpgradeTo", "Ressource"};
int i;
UnitTypeVar.VariableName = calloc(NVARALREADYDEFINED, sizeof(*UnitTypeVar.VariableName));
for (i = 0; i < NVARALREADYDEFINED; i++) {
UnitTypeVar.VariableName[i] = strdup(var[i]);
}
UnitTypeVar.Variable = calloc(i, sizeof(*UnitTypeVar.Variable));
UnitTypeVar.NumberVariable = i;
#undef NVARALREADYDEFINED
}
/**
** Register CCL features for unit-type.
*/
@ -1242,6 +1529,10 @@ global void UnitTypeCclRegister(void)
lua_register(Lua, "DefineUnitType", CclDefineUnitType);
lua_register(Lua, "DefineUnitStats", CclDefineUnitStats);
lua_register(Lua, "DefineBoolFlags", CclDefineBoolFlags);
lua_register(Lua, "DefineVariables", CclDefineVariables);
lua_register(Lua, "DefineDecorations", CclDefineDecorations);
InitDefinedVariables();
lua_register(Lua, "UnitType", CclUnitType);
lua_register(Lua, "UnitTypeArray", CclUnitTypeArray);

View file

@ -311,6 +311,11 @@ global void InitUnit(Unit* unit, UnitType* type)
(type->Building ? 0 : type->NumDirections / 2 + 1 - 1);
}
if (UnitTypeVar.NumberVariable) {
unit->Variable = malloc(UnitTypeVar.NumberVariable * sizeof(*unit->Variable));
memcpy(unit->Variable, unit->Type->Variable, UnitTypeVar.NumberVariable * sizeof(*unit->Variable));
}
if (!type->Building && type->Sprite &&
VideoGraphicFrames(type->Sprite) > 5) {
unit->Direction = (MyRand() >> 8) & 0xFF; // random heading
@ -3049,7 +3054,7 @@ global int CanTarget(const UnitType* source, const UnitType* dest)
{
int i;
for (i = 0; i < NumberBoolFlag; i++) {
for (i = 0; i < UnitTypeVar.NumberBoolFlag; i++) {
if (source->CanTargetFlag[i] != CONDITION_TRUE) {
if ((source->CanTargetFlag[i] == CONDITION_ONLY) ^ (dest->BoolFlag[i])) {
return 0;
@ -3320,6 +3325,12 @@ global void SaveUnit(const Unit* unit, CLFile* file)
CLprintf(file, "\"flame-shield\", %d, ", unit->FlameShield);
CLprintf(file, "\"unholy-armor\", %d,\n ", unit->UnholyArmor);
for (i = 0; i < UnitTypeVar.NumberVariable; i++) {
CLprintf(file, "\"%s\", {Value = %d, Max = %d, Increase = %d, Enable = %s},\n ",
UnitTypeVar.VariableName[i], unit->Variable[i].Value, unit->Variable[i].Max,
unit->Variable[i].Increase, unit->Variable[i].Enable ? "true" : "false");
}
CLprintf(file, "\"group-id\", %d,\n ", unit->GroupId);
CLprintf(file, "\"last-group\", %d,\n ", unit->LastGroup);
@ -3580,6 +3591,7 @@ global void CleanUnits(void)
//
for (table = Units; table < &Units[NumUnits]; ++table) {
free((*table)->AutoCastSpell);
free((*table)->Variable);
free(*table);
*table = NULL;
}
@ -3591,7 +3603,6 @@ global void CleanUnits(void)
ReleasedHead = unit->Next;
free(unit);
}
InitUnitsMemory();
XpDamage = 0;

File diff suppressed because it is too large Load diff

View file

@ -927,6 +927,7 @@ global void CleanUnitTypes(void)
Assert(type->Name);
free(type->Name);
free(type->Variable);
free(type->BoolFlag);
free(type->CanTargetFlag);
@ -1016,12 +1017,17 @@ global void CleanUnitTypes(void)
}
NumUnitTypes = 0;
for (i = 0; i < NumberBoolFlag; i++) { // User defined flags
free(BoolFlagName[i]);
for (i = 0; i < UnitTypeVar.NumberBoolFlag; i++) { // User defined flags
free(UnitTypeVar.BoolFlagName[i]);
}
free(BoolFlagName);
BoolFlagName = NULL;
NumberBoolFlag = 0;
for (i = 0; i < UnitTypeVar.NumberVariable; i++) { // User defined variables
free(UnitTypeVar.VariableName[i]);
}
free(UnitTypeVar.BoolFlagName);
free(UnitTypeVar.VariableName);
free(UnitTypeVar.Variable);
free(UnitTypeVar.DecoVar);
memset(&UnitTypeVar, 0, sizeof (UnitTypeVar));
//
// Clean hardcoded unit types.