9 changes: 6 additions & 3 deletions data/mp/multiplay/skirmish/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,20 @@ function eventDestroyed(victim)

function eventResearched(research, structure, player)
{
//debug("RESEARCH : " + research.fullname + "(" + research.name + ") for " + player);
//if (research.name == "") debug("RESEARCH : " + research.fullname + "(" + research.name + ") for " + player);
// iterate over all results
for (var i = 0; i < research.results.length; i++)
{
var v = research.results[i];
//debug(" RESULT : class=" + v['class'] + " parameter=" + v['parameter'] + " value=" + v['value'] + " filter=" + v['filterParameter'] + " filterval=" + v['filterValue']);
//if (research.name == "") debug(" RESULT : class=" + v['class'] + " parameter=" + v['parameter'] + " value=" + v['value'] + " filter=" + v['filterParameter'] + " filterval=" + v['filterValue']);
for (var cname in Upgrades[player][v['class']]) // iterate over all components of this type
{
var parameter = v['parameter'];
var ctype = v['class'];
var filterparam = v['filterParameter'];
if ('filterParameter' in v && Stats[ctype][cname][filterparam] != v['filterValue']) // more specific filter
{
//if (research.name == "") debug(" skipped param=" + parameter + " cname=" + cname);
continue;
}
if (Stats[ctype][cname][parameter] instanceof Array)
Expand All @@ -362,8 +363,9 @@ function eventResearched(research, structure, player)
else if (Stats[ctype][cname][parameter] > 0) // only applies if stat has above zero value already
{
Upgrades[player][ctype][cname][parameter] += Math.ceil(Stats[ctype][cname][parameter] * v['value'] / 100);
//debug(" upgraded " + cname + " to " + Upgrades[player][ctype][cname][parameter] + " by " + Math.ceil(Stats[ctype][cname][parameter] * v['value'] / 100));
//if (research.name == "") debug(" upgraded " + cname + " to " + Upgrades[player][ctype][cname][parameter] + " by " + Math.ceil(Stats[ctype][cname][parameter] * v['value'] / 100));
}
//else if (research.name == "") debug(" passed " + Stats[ctype][cname][parameter] + " param=" + parameter + " cname=" + cname);
}
}
}
Expand Down Expand Up @@ -397,6 +399,7 @@ function eventChat(from, to, message)
if (Upgrades[from].Body[i].bodyClass === 'Droids' || Upgrades[from].Body[i].bodyClass === 'Cyborgs')
{
Upgrades[from].Body[i].HitPoints += 500;
Upgrades[from].Body[i].HitPointPct += 100;
Upgrades[from].Body[i].Armour += 500;
Upgrades[from].Body[i].Thermal += 500;
Upgrades[from].Body[i].Power += 500;
Expand Down
18 changes: 8 additions & 10 deletions data/mp/stats/propulsion.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"BaBaLegs": {
"buildPoints": 15,
"deceleration": 450,
"hitpoints": 1,
"id": "BaBaLegs",
"name": "BaBaLegs",
"speed": 200,
Expand All @@ -14,7 +13,6 @@
},
"BaBaProp": {
"buildPoints": 15,
"hitpoints": 1,
"id": "BaBaProp",
"name": "BaBaProp",
"speed": 200,
Expand All @@ -25,7 +23,7 @@
"buildPoints": 50,
"buildPower": 10,
"deceleration": 450,
"hitpoints": 50,
"hitpointPctOfBody": 50,
"id": "CyborgLegs",
"name": "Cyborg Propulsion",
"speed": 400,
Expand All @@ -39,7 +37,7 @@
"buildPoints": 75,
"buildPower": 75,
"designable": 1,
"hitpoints": 200,
"hitpointPctOfBody": 200,
"id": "HalfTrack",
"model": "PRLRHTR1.PIE",
"name": "Half-tracks",
Expand All @@ -54,7 +52,7 @@
"buildPower": 150,
"deceleration": 200,
"designable": 1,
"hitpoints": 100,
"hitpointPctOfBody": 100,
"id": "Helicopter",
"model": "PRLHELI1.PIE",
"name": "Helicopter",
Expand All @@ -68,7 +66,7 @@
"buildPoints": 150,
"buildPower": 150,
"designable": 1,
"hitpoints": 300,
"hitpointPctOfBody": 300,
"id": "Naval",
"model": "prhnaval1.pie",
"name": "Naval",
Expand All @@ -82,7 +80,7 @@
"buildPower": 150,
"deceleration": 200,
"designable": 1,
"hitpoints": 100,
"hitpointPctOfBody": 100,
"id": "V-Tol",
"model": "DPVTOL.PIE",
"name": "VTOL",
Expand All @@ -102,7 +100,7 @@
"buildPoints": 100,
"buildPower": 150,
"designable": 1,
"hitpoints": 100,
"hitpointPctOfBody": 100,
"id": "hover01",
"model": "PRLHOV1.PIE",
"name": "Hover",
Expand All @@ -115,7 +113,7 @@
"buildPoints": 125,
"buildPower": 125,
"designable": 1,
"hitpoints": 300,
"hitpointPctOfBody": 300,
"id": "tracked01",
"model": "PRLRTRK1.PIE",
"name": "Tracks",
Expand All @@ -128,7 +126,7 @@
"buildPoints": 50,
"buildPower": 50,
"designable": 1,
"hitpoints": 100,
"hitpointPctOfBody": 100,
"id": "wheeled01",
"model": "PRLRWHL1.PIE",
"name": "Wheels",
Expand Down
43 changes: 25 additions & 18 deletions data/mp/stats/research.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
"filterValue": "CommandBrain01",
"parameter": "RankThresholds",
"value": -10
},
{
"class": "Brain",
"filterParameter": "Id",
"filterValue": "CommandBrain01",
"parameter": "HitPoints",
"value": 20
}
],
"statID": "CommandBrain01"
Expand Down Expand Up @@ -396,7 +403,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -424,7 +431,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -453,7 +460,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -487,7 +494,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -515,7 +522,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -544,7 +551,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -574,7 +581,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -602,7 +609,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 25
}
],
Expand Down Expand Up @@ -631,7 +638,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Cyborgs",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 35
}
],
Expand Down Expand Up @@ -4289,7 +4296,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4317,7 +4324,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4347,7 +4354,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4378,7 +4385,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4406,7 +4413,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4435,7 +4442,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4466,7 +4473,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4494,7 +4501,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down Expand Up @@ -4523,7 +4530,7 @@
"class": "Body",
"filterParameter": "BodyClass",
"filterValue": "Droids",
"parameter": "HitPoints",
"parameter": "HitPointPct",
"value": 30
}
],
Expand Down
2 changes: 1 addition & 1 deletion data/mp/stats/weapons.json
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@
"flightGfx": "FXBeam.PIE",
"flightSpeed": 2500,
"hitGfx": "FXSFlms.PIE",
"hitpoints": 1000,
"hitpoints": 500,
"id": "CommandTurret1",
"lightWorld": 1,
"longRange": 1536,
Expand Down
29 changes: 14 additions & 15 deletions src/design.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2533,6 +2533,7 @@ static void intSetBodyPoints(DROID_TEMPLATE *psTemplate)
/* Set the shadow bar graphs for the template Body points - psStats is new hilited stats*/
static void intSetTemplateBodyShadowStats(COMPONENT_STATS *psStats)
{
const int plr = selectedPlayer;
if (!psStats)
{
/* Reset the shadow bar */
Expand All @@ -2542,24 +2543,24 @@ static void intSetTemplateBodyShadowStats(COMPONENT_STATS *psStats)

COMPONENT_TYPE type = psStats->compType;
UDWORD body;
UDWORD bodyBody = asBodyStats[sCurrDesign.asParts[COMP_BODY]].body;
uint32_t bodyUpgradeBody = asBodyStats[sCurrDesign.asParts[COMP_BODY]].upgrade[selectedPlayer].body;
UDWORD brainBody = asBrainStats[sCurrDesign.asParts[COMP_BRAIN]].body;
UDWORD sensorBody = asSensorStats[sCurrDesign.asParts[COMP_SENSOR]].body;
UDWORD ECMBody = asECMStats[sCurrDesign.asParts[COMP_ECM]].body;
UDWORD repairBody = asRepairStats[sCurrDesign.asParts[COMP_REPAIRUNIT]].body;
UDWORD constructBody = asConstructStats[sCurrDesign.asParts[COMP_CONSTRUCT]].body;
UDWORD propulsionBody = asPropulsionStats[sCurrDesign.asParts[COMP_PROPULSION]].body;
UDWORD weaponBody1 = asWeaponStats[sCurrDesign.numWeaps ? sCurrDesign.asWeaps[0] : 0].body;
UDWORD weaponBody2 = asWeaponStats[sCurrDesign.numWeaps >= 2 ? sCurrDesign.asWeaps[1] : 0].body;
UDWORD weaponBody3 = asWeaponStats[sCurrDesign.numWeaps >= 3 ? sCurrDesign.asWeaps[2] : 0].body;
UDWORD newComponentBody = psStats->body;
UDWORD bodyBody = asBodyStats[sCurrDesign.asParts[COMP_BODY]].upgrade[plr].hitpoints;
UDWORD brainBody = asBrainStats[sCurrDesign.asParts[COMP_BRAIN]].upgrade[plr].hitpoints;
UDWORD sensorBody = asSensorStats[sCurrDesign.asParts[COMP_SENSOR]].upgrade[plr].hitpoints;
UDWORD ECMBody = asECMStats[sCurrDesign.asParts[COMP_ECM]].upgrade[plr].hitpoints;
UDWORD repairBody = asRepairStats[sCurrDesign.asParts[COMP_REPAIRUNIT]].upgrade[plr].hitpoints;
UDWORD constructBody = asConstructStats[sCurrDesign.asParts[COMP_CONSTRUCT]].upgrade[plr].hitpoints;
UDWORD propulsionBody = asPropulsionStats[sCurrDesign.asParts[COMP_PROPULSION]].upgrade[plr].hitpoints;
UDWORD weaponBody1 = asWeaponStats[sCurrDesign.numWeaps ? sCurrDesign.asWeaps[0] : 0].upgrade[plr].hitpoints;
UDWORD weaponBody2 = asWeaponStats[sCurrDesign.numWeaps >= 2 ? sCurrDesign.asWeaps[1] : 0].upgrade[plr].hitpoints;
UDWORD weaponBody3 = asWeaponStats[sCurrDesign.numWeaps >= 3 ? sCurrDesign.asWeaps[2] : 0].upgrade[plr].hitpoints;
UDWORD newComponentBody = psStats->pUpgrade[plr]->hitpoints;

// Commanders receive the stats of their associated weapon.
if (type == COMP_BRAIN)
{
newComponentBody += ((BRAIN_STATS *)psStats)->psWeaponStat->body;
newComponentBody += ((BRAIN_STATS *)psStats)->psWeaponStat->upgrade[plr].hitpoints;
}

/*if type = BODY or PROPULSION can do a straight comparison but if the new stat is
a 'system' stat then need to find out which 'system' is currently in place so the
comparison is meaningful*/
Expand All @@ -2572,7 +2573,6 @@ static void intSetTemplateBodyShadowStats(COMPONENT_STATS *psStats)
{
case COMP_BODY:
bodyBody = newComponentBody;
bodyUpgradeBody = ((BODY_STATS *)psStats)->upgrade[selectedPlayer].body;
break;
case COMP_PROPULSION:
propulsionBody = newComponentBody;
Expand Down Expand Up @@ -2617,7 +2617,6 @@ static void intSetTemplateBodyShadowStats(COMPONENT_STATS *psStats)

//add weapon HP
body += weaponBody1 + weaponBody2 + weaponBody3;
body = body * bodyUpgradeBody / std::max(bodyBody, 1u);
widgSetMinorBarSize(psWScreen, IDDES_BODYPOINTS, body);
}

Expand Down
41 changes: 25 additions & 16 deletions src/droid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1388,33 +1388,42 @@ UDWORD calcDroidWeight(DROID_TEMPLATE *psTemplate)

static uint32_t calcDroidOrTemplateBody(uint8_t (&asParts)[DROID_MAXCOMP], unsigned numWeaps, uint8_t (&asWeaps)[MAX_WEAPONS], unsigned player)
{
auto &bodyStats = asBodyStats[asParts[COMP_BODY]];
const auto &bodyStats = asBodyStats[asParts[COMP_BODY]];

// Get the basic component body points
uint32_t body =
bodyStats.body +
asBrainStats[asParts[COMP_BRAIN]].body +
asSensorStats[asParts[COMP_SENSOR]].body +
asECMStats[asParts[COMP_ECM]].body +
asRepairStats[asParts[COMP_REPAIRUNIT]].body +
asConstructStats[asParts[COMP_CONSTRUCT]].body;

// propulsion body points are a percentage of the body's body points
body += bodyStats.body * asPropulsionStats[asParts[COMP_PROPULSION]].body / 100;
int hitpoints =
bodyStats.upgrade[player].hitpoints +
asBrainStats[asParts[COMP_BRAIN]].upgrade[player].hitpoints +
asSensorStats[asParts[COMP_SENSOR]].upgrade[player].hitpoints +
asECMStats[asParts[COMP_ECM]].upgrade[player].hitpoints +
asRepairStats[asParts[COMP_REPAIRUNIT]].upgrade[player].hitpoints +
asPropulsionStats[asParts[COMP_PROPULSION]].upgrade[player].hitpoints +
asConstructStats[asParts[COMP_CONSTRUCT]].upgrade[player].hitpoints;

int hitpointpct =
bodyStats.upgrade[player].hitpointPct - 100 +
asBrainStats[asParts[COMP_BRAIN]].upgrade[player].hitpointPct - 100 +
asSensorStats[asParts[COMP_SENSOR]].upgrade[player].hitpointPct - 100 +
asECMStats[asParts[COMP_ECM]].upgrade[player].hitpointPct - 100 +
asRepairStats[asParts[COMP_REPAIRUNIT]].upgrade[player].hitpointPct - 100 +
asPropulsionStats[asParts[COMP_PROPULSION]].upgrade[player].hitpointPct - 100 +
asConstructStats[asParts[COMP_CONSTRUCT]].upgrade[player].hitpointPct - 100;

// propulsion hitpoints can be a percentage of the body's hitpoints
hitpoints += bodyStats.upgrade[player].hitpoints * asPropulsionStats[asParts[COMP_PROPULSION]].upgrade[player].hitpointPctOfBody / 100;

// Add the weapon body points
for (unsigned i = 0; i < numWeaps; ++i)
{
if (asWeaps[i] > 0)
{
body += asWeaponStats[asWeaps[i]].body;
hitpoints += asWeaponStats[asWeaps[i]].upgrade[player].hitpoints;
hitpointpct += asWeaponStats[asWeaps[i]].upgrade[player].hitpointPct - 100;
}
}

//add on any upgrade value that may need to be applied
body = body * bodyStats.upgrade[player].body / std::max(bodyStats.body, 1u);

return body;
// Final adjustment based on the hitpoint modifier
return (hitpoints * (100 + hitpointpct)) / 100;
}

// Calculate the body points of a droid from its template
Expand Down
2 changes: 1 addition & 1 deletion src/oprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static void printComponentInfo(const COMPONENT_STATS *psStats)
CONPRINTF(ConsoleString, (ConsoleString, "%s ref %d\n"
" bPwr %d bPnts %d wt %d bdy %d imd %p\n",
getName(psStats), psStats->ref, psStats->buildPower,
psStats->buildPoints, psStats->weight, psStats->body,
psStats->buildPoints, psStats->weight, psStats->pBase->hitpoints,
psStats->pIMD));
}

Expand Down
4 changes: 3 additions & 1 deletion src/qtscriptdebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ QStandardItemList componentToString(const QString &name, const COMPONENT_STATS *
key->appendRow(QStandardItemList{ new QStandardItem("^Power"), new QStandardItem(QString::number(psStats->buildPower)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Build Points"), new QStandardItem(QString::number(psStats->buildPoints)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Weight"), new QStandardItem(QString::number(psStats->weight)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Hit points"), new QStandardItem(QString::number(psStats->body)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Hit points"), new QStandardItem(QString::number(psStats->pUpgrade[player]->hitpoints)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Hit points +% of total"), new QStandardItem(QString::number(psStats->pUpgrade[player]->hitpointPct)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Designable"), new QStandardItem(QString::number(psStats->designable)) });
if (psStats->compType == COMP_BODY)
{
Expand All @@ -398,6 +399,7 @@ QStandardItemList componentToString(const QString &name, const COMPONENT_STATS *
else if (psStats->compType == COMP_PROPULSION)
{
const PROPULSION_STATS *psProp = (const PROPULSION_STATS *)psStats;
key->appendRow(QStandardItemList{ new QStandardItem("^Hit points +% of body"), new QStandardItem(QString::number(psProp->upgrade[player].hitpointPctOfBody)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Max speed"), new QStandardItem(QString::number(psProp->maxSpeed)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Propulsion type"), new QStandardItem(QString::number(psProp->propulsionType)) });
key->appendRow(QStandardItemList{ new QStandardItem("^Turn speed"), new QStandardItem(QString::number(psProp->turnSpeed)) });
Expand Down
334 changes: 268 additions & 66 deletions src/qtscriptfuncs.cpp

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions src/stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,10 @@ static void loadCompStats(WzConfig &json, COMPONENT_STATS *psStats, int index)
loadStats(json, psStats, index);
psStats->buildPower = json.value("buildPower", 0).toUInt();
psStats->buildPoints = json.value("buildPoints", 0).toUInt();
psStats->body = json.value("hitpoints", 0).toUInt();
psStats->designable = json.value("designable", false).toBool();
psStats->weight = json.value("weight", 0).toUInt();
psStats->pBase->hitpoints = json.value("hitpoints", 0).toUInt();
psStats->pBase->hitpointPct = json.value("hitpointPct", 100).toUInt();
}

/*Load the weapon stats from the file exported from Access*/
Expand Down Expand Up @@ -527,7 +528,6 @@ bool loadBodyStats(const char *pFileName)
psStats->base.thermal = ini.value("armourHeat").toInt();
psStats->base.armour = ini.value("armourKinetic").toInt();
psStats->base.power = ini.value("powerOutput").toInt();
psStats->base.body = psStats->body; // special exception hack
psStats->base.resistance = ini.value("resistance", 30).toInt();
for (int j = 0; j < MAX_PLAYERS; j++)
{
Expand Down Expand Up @@ -575,7 +575,7 @@ bool loadBodyStats(const char *pFileName)
setMaxBodyArmour(psStats->base.armour);
setMaxBodyArmour(psStats->base.thermal);
setMaxBodyPower(psStats->base.power);
setMaxBodyPoints(psStats->body);
setMaxBodyPoints(psStats->base.hitpoints);
setMaxComponentWeight(psStats->weight);
}
}
Expand Down Expand Up @@ -758,6 +758,7 @@ bool loadPropulsionStats(const char *pFileName)
loadCompStats(ini, psStats, i);
psStats->compType = COMP_PROPULSION;

psStats->base.hitpointPctOfBody = ini.value("hitpointPctOfBody", 0).toInt();
psStats->maxSpeed = ini.value("speed").toInt();
psStats->ref = REF_PROPULSION_START + i;
psStats->turnSpeed = ini.value("turnSpeed", DEG(1) / 3).toInt();
Expand All @@ -768,6 +769,10 @@ bool loadPropulsionStats(const char *pFileName)
psStats->skidDeceleration = ini.value("skidDeceleration", 600).toInt();
psStats->pIMD = nullptr;
psStats->pIMD = statsGetIMD(ini, psStats, "model");
for (int j = 0; j < MAX_PLAYERS; j++)
{
psStats->upgrade[j] = psStats->base;
}
if (!getPropulsionType(ini.value("type").toString().toUtf8().constData(), &psStats->propulsionType))
{
debug(LOG_FATAL, "loadPropulsionStats: Invalid Propulsion type for %s", getName(psStats));
Expand Down Expand Up @@ -828,7 +833,7 @@ bool loadSensorStats(const char *pFileName)
psStats->base.range = ini.value("range").toInt();
for (int j = 0; j < MAX_PLAYERS; j++)
{
psStats->upgrade[j].range = psStats->base.range;
psStats->upgrade[j] = psStats->base;
}

psStats->ref = REF_SENSOR_START + i;
Expand Down Expand Up @@ -914,7 +919,7 @@ bool loadECMStats(const char *pFileName)
psStats->base.range = ini.value("range").toInt();
for (int j = 0; j < MAX_PLAYERS; j++)
{
psStats->upgrade[j].range = psStats->base.range;
psStats->upgrade[j] = psStats->base;
}

psStats->ref = REF_ECM_START + i;
Expand Down Expand Up @@ -970,7 +975,7 @@ bool loadRepairStats(const char *pFileName)
psStats->base.repairPoints = ini.value("repairPoints").toInt();
for (int j = 0; j < MAX_PLAYERS; j++)
{
psStats->upgrade[j].repairPoints = psStats->base.repairPoints;
psStats->upgrade[j] = psStats->base;
}
psStats->time = ini.value("time", 0).toInt() * WEAPON_TIME;

Expand Down Expand Up @@ -1030,7 +1035,7 @@ bool loadConstructStats(const char *pFileName)
psStats->base.constructPoints = ini.value("constructPoints").toInt();
for (int j = 0; j < MAX_PLAYERS; j++)
{
psStats->upgrade[j].constructPoints = psStats->base.constructPoints;
psStats->upgrade[j] = psStats->base;
}
psStats->ref = REF_CONSTRUCT_START + i;

Expand Down Expand Up @@ -1980,7 +1985,7 @@ void adjustMaxDesignStats()
for (int j = 0; j < numBodyStats; j++)
{
BODY_STATS *psStats = asBodyStats + j;
bodyPoints = MAX(bodyPoints, psStats->upgrade[selectedPlayer].body);
bodyPoints = MAX(bodyPoints, psStats->upgrade[selectedPlayer].hitpoints);
bodyArmour = MAX(bodyArmour, psStats->upgrade[selectedPlayer].armour);
bodyPower = MAX(bodyPower, psStats->upgrade[selectedPlayer].power);
}
Expand Down
118 changes: 71 additions & 47 deletions src/statsdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,83 +259,103 @@ struct BASE_STATS
/* Stats common to all droid components */
struct COMPONENT_STATS : public BASE_STATS
{
COMPONENT_STATS() : buildPower(0), buildPoints(0), weight(0), body(0), designable(false), pIMD(nullptr),
COMPONENT_STATS() : buildPower(0), buildPoints(0), weight(0), designable(false), pIMD(nullptr),
compType(COMP_NUMCOMPONENTS) {}

UDWORD buildPower; /**< Power required to build the component */
UDWORD buildPoints; /**< Time required to build the component */
UDWORD weight; /**< Component's weight */
UDWORD body; /**< Component's body points */
bool designable; /**< flag to indicate whether this component can be used in the design screen */
iIMDShape *pIMD; /**< The IMD to draw for this component */
COMPONENT_TYPE compType;

struct UPGRADE
{
/// Number of upgradeable hitpoints
unsigned hitpoints = 0;
/// Adjust final droid hitpoints by this percentage amount
int hitpointPct = 100;
};

UPGRADE *pBase = nullptr;
UPGRADE *pUpgrade[MAX_PLAYERS] = { nullptr };
};

struct PROPULSION_STATS : public COMPONENT_STATS
{
PROPULSION_STATS() : maxSpeed(0), propulsionType(PROPULSION_TYPE_NUM), turnSpeed(0), spinSpeed(0),
spinAngle(0), skidDeceleration(0), deceleration(0), acceleration(0) {}
spinAngle(0), skidDeceleration(0), deceleration(0), acceleration(0)
{
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

UDWORD maxSpeed; ///< Max speed for the droid
UDWORD maxSpeed; ///< Max speed for the droid
PROPULSION_TYPE propulsionType; ///< Type of propulsion used - index into PropulsionTable
UDWORD turnSpeed;
UDWORD spinSpeed;
UDWORD spinAngle;
UDWORD skidDeceleration;
UDWORD deceleration;
UDWORD acceleration;
UDWORD turnSpeed;
UDWORD spinSpeed;
UDWORD spinAngle;
UDWORD skidDeceleration;
UDWORD deceleration;
UDWORD acceleration;

struct : UPGRADE
{
/// Increase hitpoints by this percentage of the body's hitpoints
int hitpointPctOfBody = 0;
} upgrade[MAX_PLAYERS], base;
};

struct SENSOR_STATS : public COMPONENT_STATS
{
SENSOR_STATS() : location(0), type(STANDARD_SENSOR), pMountGraphic(nullptr)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

UDWORD location; ///< specifies whether the Sensor is default or for the Turret
SENSOR_TYPE type; ///< used for combat
iIMDShape *pMountGraphic; ///< The turret mount to use

struct
struct : UPGRADE
{
unsigned range;
unsigned range = 0;
} upgrade[MAX_PLAYERS], base;
};

struct ECM_STATS : public COMPONENT_STATS
{
ECM_STATS() : location(0), pMountGraphic(nullptr)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

UDWORD location; ///< specifies whether the ECM is default or for the Turret
iIMDShape *pMountGraphic; ///< The turret mount to use

struct
struct : UPGRADE
{
unsigned range;
unsigned range = 0;
} upgrade[MAX_PLAYERS], base;
};

struct REPAIR_STATS : public COMPONENT_STATS
{
REPAIR_STATS() : location(0), time(0), pMountGraphic(nullptr)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

UDWORD location; ///< specifies whether the Repair is default or for the Turret
UDWORD time; ///< time delay for repair cycle
iIMDShape *pMountGraphic; ///< The turret mount to use

struct
struct : UPGRADE
{
unsigned repairPoints; ///< The number of points contributed each cycle
unsigned repairPoints = 0; ///< The number of points contributed each cycle
} upgrade[MAX_PLAYERS], base;
};

Expand All @@ -345,25 +365,25 @@ struct WEAPON_STATS : public COMPONENT_STATS
pTargetMissGraphic(nullptr), pWaterHitGraphic(nullptr), pTrailGraphic(nullptr), iAudioFireID(0),
iAudioImpactID(0)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

struct
struct : UPGRADE
{
unsigned maxRange; ///< Max distance to target for long range shot
unsigned minRange; ///< Min distance to target for shot
unsigned hitChance; ///< Chance to hit at
unsigned firePause; ///< Pause between each shot
uint8_t numRounds; ///< The number of rounds per salvo
unsigned reloadTime; ///< Time to reload the round of ammo
unsigned damage;
unsigned radius; ///< Basic blast radius of weapon
unsigned radiusDamage; ///< "Splash damage"
unsigned periodicalDamage; ///< Repeat damage each second after hit
unsigned periodicalDamageRadius; ///< Repeat damage radius
unsigned periodicalDamageTime; ///< How long the round keeps damaging
unsigned minimumDamage; ///< Minimum amount of damage done, in percentage of damage
unsigned maxRange = 0; ///< Max distance to target for long range shot
unsigned minRange = 0; ///< Min distance to target for shot
unsigned hitChance = 0; ///< Chance to hit at
unsigned firePause = 0; ///< Pause between each shot
uint8_t numRounds = 0; ///< The number of rounds per salvo
unsigned reloadTime = 0; ///< Time to reload the round of ammo
unsigned damage = 0;
unsigned radius = 0; ///< Basic blast radius of weapon
unsigned radiusDamage = 0; ///< "Splash damage"
unsigned periodicalDamage = 0; ///< Repeat damage each second after hit
unsigned periodicalDamageRadius = 0; ///< Repeat damage radius
unsigned periodicalDamageTime = 0; ///< How long the round keeps damaging
unsigned minimumDamage = 0; ///< Minimum amount of damage done, in percentage of damage
} base, upgrade[MAX_PLAYERS];

WEAPON_CLASS periodicalDamageWeaponClass; ///< Periodical damage weapon class by damage type (KINETIC, HEAT)
Expand Down Expand Up @@ -412,24 +432,29 @@ struct CONSTRUCT_STATS : public COMPONENT_STATS
{
CONSTRUCT_STATS() : pMountGraphic(nullptr)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

iIMDShape *pMountGraphic; ///< The turret mount to use

struct
struct : UPGRADE
{
unsigned constructPoints; ///< The number of points contributed each cycle
} upgrade[MAX_PLAYERS], base;
};

struct BRAIN_STATS : public COMPONENT_STATS
{
BRAIN_STATS() : psWeaponStat(nullptr) {}
BRAIN_STATS() : psWeaponStat(nullptr)
{
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

WEAPON_STATS *psWeaponStat; ///< weapon stats associated with this brain - for Command Droids
struct

struct : UPGRADE
{
int maxDroids = 0; ///< base maximum number of droids that the commander can control
int maxDroidsMult = 0; ///< maximum number of controlled droids multiplied by level
Expand All @@ -448,8 +473,8 @@ struct BODY_STATS : public COMPONENT_STATS
{
BODY_STATS() : size(SIZE_NUM), weaponSlots(0), droidTypeOverride(DROID_ANY)
{
memset(&upgrade, 0, sizeof(upgrade));
memset(&base, 0, sizeof(base));
pBase = &base;
for (int i = 0; i < MAX_PLAYERS; i++) pUpgrade[i] = &upgrade[i];
}

BODY_SIZE size; ///< How big the body is - affects how hit
Expand All @@ -461,10 +486,9 @@ struct BODY_STATS : public COMPONENT_STATS
std::vector<iIMDShape *> ppStillIMDList;///< list of IMDs to use when droid is still - up to numPropulsionStats
QString bodyClass; ///< rules hint to script about its classification

struct
struct : UPGRADE
{
unsigned power; ///< this is the engine output of the body
unsigned body;
unsigned armour; ///< A measure of how much protection the armour provides
int thermal;
int resistance;
Expand Down
8 changes: 4 additions & 4 deletions src/structuredef.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,13 +315,13 @@ struct ProductionRunEntry
};
typedef std::vector<ProductionRunEntry> ProductionRun;

struct UPGRADE
struct UPGRADE_MOD
{
UWORD modifier; //% to increase the stat by
};

typedef UPGRADE REPAIR_FACILITY_UPGRADE;
typedef UPGRADE POWER_UPGRADE;
typedef UPGRADE REARM_UPGRADE;
typedef UPGRADE_MOD REPAIR_FACILITY_UPGRADE;
typedef UPGRADE_MOD POWER_UPGRADE;
typedef UPGRADE_MOD REARM_UPGRADE;

#endif // __INCLUDED_STRUCTUREDEF_H__