[+] Applied Andrettin's patch for SetPlayerData, https://bugs.launchpad.net/stratagus/+bug/1331628

This commit is contained in:
cybermind 2015-02-12 22:27:37 +05:00
parent 51647d9be9
commit 65487e9e2a
4 changed files with 167 additions and 15 deletions

View file

@ -89,6 +89,7 @@ extern void UpgradeLost(CPlayer &player, int id);
// id -- unit type id, af -- `A'llow/`F'orbid
extern int UnitIdAllowed(const CPlayer &player, int id);
extern void AllowUpgradeId(CPlayer &player, int id, char af);
extern char UpgradeIdAllowed(const CPlayer &player, int id);
extern char UpgradeIdentAllowed(const CPlayer &player, const std::string &ident);

View file

@ -180,7 +180,7 @@ public:
class CUpgradeModifier
{
public:
CUpgradeModifier() : UpgradeId(0), ModifyPercent(NULL), ConvertTo(NULL)
CUpgradeModifier() : UpgradeId(0), ModifyPercent(NULL), SpeedResearch(0), ConvertTo(NULL)
{
memset(ChangeUnits, 0, sizeof(ChangeUnits));
memset(ChangeUpgrades, 0, sizeof(ChangeUpgrades));
@ -194,7 +194,8 @@ public:
int UpgradeId; /// used to filter required modifier
CUnitStats Modifier; /// modifier of unit stats.
int *ModifyPercent; /// use for percent modifiers
int *ModifyPercent; /// use for percent modifiers
int SpeedResearch; /// speed factor for researching
// allow/forbid bitmaps -- used as chars for example:
// `?' -- leave as is, `F' -- forbid, `A' -- allow

View file

@ -842,6 +842,23 @@ static int CclSetPlayerData(lua_State *l)
p->SpeedUpgrade = LuaToNumber(l, 3);
} else if (!strcmp(data, "SpeedResearch")) {
p->SpeedResearch = LuaToNumber(l, 3);
} else if (!strcmp(data, "Allow")) {
LuaCheckArgs(l, 4);
const char *ident = LuaToString(l, 3);
const std::string acquire = LuaToString(l, 4);
if (!strncmp(ident, "upgrade-", 8)) {
if (acquire == "R" && UpgradeIdentAllowed(*p, ident) != 'R') {
UpgradeAcquire(*p, CUpgrade::Get(ident));
} else if (acquire == "F" || acquire == "A") {
if (UpgradeIdentAllowed(*p, ident) == 'R') {
UpgradeLost(*p, CUpgrade::Get(ident)->ID);
}
AllowUpgradeId(*p, UpgradeIdByIdent(ident), acquire[0]);
}
} else {
LuaError(l, " wrong ident %s\n" _C_ ident);
}
} else {
LuaError(l, "Invalid field: %s" _C_ data);
}

View file

@ -59,7 +59,6 @@
----------------------------------------------------------------------------*/
static void AllowUnitId(CPlayer &player, int id, int units);
static void AllowUpgradeId(CPlayer &player, int id, char af);
/*----------------------------------------------------------------------------
-- Variables
@ -314,6 +313,8 @@ static int CclDefineModifier(lua_State *l)
} else if (!strcmp(key, "convert-to")) {
const char *value = LuaToString(l, j + 1, 2);
um->ConvertTo = UnitTypeByIdent(value);
} else if (!strcmp(key, "research-speed")) {
um->SpeedResearch = LuaToNumber(l, j + 1, 2);
} else {
int index = UnitTypeVar.VariableNameLookup[key]; // variable index;
if (index != -1) {
@ -621,6 +622,135 @@ static void ApplyUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
}
}
/**
** Remove the modifiers of an upgrade.
**
** This function will unmark upgrade as done and undo all required modifications
** to unit types and will modify allow/forbid maps back
**
** @param player Player that get all the upgrades.
** @param um Upgrade modifier that do the effects
*/
static void RemoveUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
{
Assert(um);
int pn = player.Index;
if (um->SpeedResearch != 0) {
player.SpeedResearch -= um->SpeedResearch;
}
for (int z = 0; z < UpgradeMax; ++z) {
// allow/forbid upgrades for player. only if upgrade is not acquired
// FIXME: check if modify is allowed
if (player.Allow.Upgrades[z] != 'R') {
if (um->ChangeUpgrades[z] == 'A') {
player.Allow.Upgrades[z] = 'F';
}
if (um->ChangeUpgrades[z] == 'F') {
player.Allow.Upgrades[z] = 'A';
}
// we can even have upgrade acquired w/o costs
if (um->ChangeUpgrades[z] == 'R') {
player.Allow.Upgrades[z] = 'A';
}
}
}
for (size_t z = 0; z < UnitTypes.size(); ++z) {
CUnitStats &stat = UnitTypes[z]->Stats[pn];
// add/remove allowed units
// FIXME: check if modify is allowed
player.Allow.Units[z] -= um->ChangeUnits[z];
Assert(um->ApplyTo[z] == '?' || um->ApplyTo[z] == 'X');
// this modifier should be applied to unittype id == z
if (um->ApplyTo[z] == 'X') {
// If Sight range is upgraded, we need to change EVERY unit
// to the new range, otherwise the counters get confused.
if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) {
std::vector<CUnit *> unitupgrade;
FindUnitsByType(*UnitTypes[z], unitupgrade);
for (size_t j = 0; j != unitupgrade.size(); ++j) {
CUnit &unit = *unitupgrade[j];
if (unit.Player->Index == pn && !unit.Removed) {
MapUnmarkUnitSight(unit);
unit.CurrentSightRange = stat.Variables[SIGHTRANGE_INDEX].Max -
um->Modifier.Variables[SIGHTRANGE_INDEX].Value;
MapMarkUnitSight(unit);
}
}
}
// upgrade costs :)
for (unsigned int j = 0; j < MaxCosts; ++j) {
stat.Costs[j] -= um->Modifier.Costs[j];
stat.Storing[j] -= um->Modifier.Storing[j];
}
int varModified = 0;
for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
varModified |= um->Modifier.Variables[j].Value
| um->Modifier.Variables[j].Max
| um->Modifier.Variables[j].Increase
| um->Modifier.Variables[j].Enable
| um->ModifyPercent[j];
stat.Variables[j].Enable |= um->Modifier.Variables[j].Enable;
if (um->ModifyPercent[j]) {
stat.Variables[j].Value = stat.Variables[j].Value * 100 / (100 + um->ModifyPercent[j]);
stat.Variables[j].Max = stat.Variables[j].Max * 100 / (100 + um->ModifyPercent[j]);
} else {
stat.Variables[j].Value -= um->Modifier.Variables[j].Value;
stat.Variables[j].Max -= um->Modifier.Variables[j].Max;
stat.Variables[j].Increase -= um->Modifier.Variables[j].Increase;
}
stat.Variables[j].Max = std::max(stat.Variables[j].Max, 0);
clamp(&stat.Variables[j].Value, 0, stat.Variables[j].Max);
}
// And now modify ingame units
if (varModified) {
std::vector<CUnit *> unitupgrade;
FindUnitsByType(*UnitTypes[z], unitupgrade, true);
for (size_t j = 0; j != unitupgrade.size(); ++j) {
CUnit &unit = *unitupgrade[j];
if (unit.Player->Index != player.Index) {
continue;
}
for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
unit.Variable[j].Enable |= um->Modifier.Variables[j].Enable;
if (um->ModifyPercent[j]) {
unit.Variable[j].Value = unit.Variable[j].Value * 100 / (100 + um->ModifyPercent[j]);
unit.Variable[j].Max = unit.Variable[j].Max * 100 / (100 + um->ModifyPercent[j]);
} else {
unit.Variable[j].Value -= um->Modifier.Variables[j].Value;
unit.Variable[j].Increase -= um->Modifier.Variables[j].Increase;
}
unit.Variable[j].Max -= um->Modifier.Variables[j].Max;
unit.Variable[j].Max = std::max(unit.Variable[j].Max, 0);
clamp(&unit.Variable[j].Value, 0, unit.Variable[j].Max);
}
}
}
if (um->ConvertTo) {
ConvertUnitTypeTo(player, *um->ConvertTo, *UnitTypes[z]);
}
}
}
}
/**
** Handle that an upgrade was acquired.
**
@ -647,20 +777,23 @@ void UpgradeAcquire(CPlayer &player, const CUpgrade *upgrade)
}
}
#if 0 // UpgradeLost not implemented.
/**
** for now it will be empty?
** perhaps acquired upgrade can be lost if (for example) a building is lost
** (lumber mill? stronghold?)
** this function will apply all modifiers in reverse way
*/
void UpgradeLost(Player &player, int id)
void UpgradeLost(CPlayer &player, int id)
{
player.UpgradeTimers.Upgrades[id] = 0;
AllowUpgradeId(player, id, 'A'); // research is lost i.e. available
// FIXME: here we should reverse apply upgrade...
for (int z = 0; z < NumUpgradeModifiers; ++z) {
if (UpgradeModifiers[z]->UpgradeId == id) {
RemoveUpgradeModifier(player, UpgradeModifiers[z]);
}
}
//
// Upgrades could change the buttons displayed.
//
if (&player == ThisPlayer) {
SelectedUnitChanged();
}
}
#endif
/*----------------------------------------------------------------------------
-- Allow(s)
@ -687,7 +820,7 @@ static void AllowUnitId(CPlayer &player, int id, int units)
** @param id upgrade id
** @param af `A'llow/`F'orbid/`R'eseached
*/
static void AllowUpgradeId(CPlayer &player, int id, char af)
void AllowUpgradeId(CPlayer &player, int id, char af)
{
Assert(af == 'A' || af == 'F' || af == 'R');
player.Allow.Upgrades[id] = af;