Skip to content

Commit cb9ed28

Browse files
committed
AND and OR kill rules
1 parent 47f1763 commit cb9ed28

4 files changed

Lines changed: 56 additions & 46 deletions

File tree

bin/data/Ruleset/Commendations.rul

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ commendations:
252252
criteria:
253253
kills_with_criteria: [3, 5, 10, 15, 20, 25, 30, 35, 40, 50]
254254
killCriteria:
255-
- ["FACTION_HOSTILE"]
255+
-
256+
- ["FACTION_HOSTILE"]
256257
- type: STR_MEDAL_MILITARY_CROSS_NAME
257258
description: STR_MEDAL_MILITARY_CROSS_DESCRIPTION
258259
sprite: 1
@@ -263,8 +264,9 @@ commendations:
263264
sprite: 2
264265
criteria:
265266
kills_with_criteria: [1, 3, 5, 7, 9, 11, 13, 15, 17, 20]
266-
killCriteria:
267-
- ["FACTION_HOSTILE", "STATUS_UNCONSCIOUS"]
267+
killCriteria:
268+
-
269+
- ["FACTION_HOSTILE", "STATUS_UNCONSCIOUS"]
268270
- type: STR_MEDAL_DEFENDER_MEDAL_NAME
269271
description: STR_MEDAL_DEFENDER_MEDAL_DESCRIPTION
270272
sprite: 3
@@ -311,22 +313,26 @@ commendations:
311313
criteria:
312314
kills_with_criteria: [1, 2, 3, 4, 5, 7, 9, 11, 15, 20]
313315
killCriteria:
314-
- ["STR_INCENDIARY_ROCKET", "FACTION_HOSTILE"]
316+
-
317+
- ["STR_INCENDIARY_ROCKET", "FACTION_HOSTILE"]
315318
- type: STR_MEDAL_DISTINGUISHED_SERVICE_NAME
316319
description: STR_MEDAL_DISTINGUISHED_SERVICE_DESCRIPTION
317320
sprite: 12
318321
criteria:
319322
kills_with_criteria: [1, 2, 3, 4, 5, 7, 9, 11, 15, 20]
320323
killCriteria:
321-
- ["STR_SECTOID", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
322-
- ["STR_FLOATER", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
323-
- ["STR_SNAKEMAN", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
324-
- ["STR_MUTON", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
325-
- ["STR_ETHEREAL", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
324+
-
325+
- ["STR_SECTOID", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
326+
- ["STR_FLOATER", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
327+
- ["STR_SNAKEMAN", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
328+
- ["STR_MUTON", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
329+
- ["STR_ETHEREAL", "STR_LIVE_SOLDIER", "FACTION_HOSTILE"]
326330
- type: STR_MEDAL_BOLTS_CROSS_NAME
327331
description: STR_MEDAL_BOLTS_CROSS_DESCRIPTION
328332
sprite: 13
329333
criteria:
330334
kills_with_criteria: [1, 2, 3, 4, 5, 7, 9, 11, 15, 20]
331-
killCriteria:
332-
- ["STR_LIVE_COMMANDER", "FACTION_HOSTILE", "STATUS_UNCONSCIOUS"]
335+
killCriteria:
336+
-
337+
- ["STR_LIVE_COMMANDER", "FACTION_HOSTILE", "STATUS_UNCONSCIOUS"]
338+
- ["STR_LIVE_LEADER", "FACTION_HOSTILE", "STATUS_UNCONSCIOUS"]

src/Ruleset/RuleCommendations.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void RuleCommendations::load(const YAML::Node &node, int listOrder)
4444
{
4545
_description = node["description"].as<std::string>(_description);
4646
_criteria = node["criteria"].as< std::map< std::string, std::vector<int> > >(_criteria);
47-
_killCriteria = node["killCriteria"].as< std::vector< std::vector<std::string> > >(_killCriteria);
47+
_killCriteria = node["killCriteria"].as< std::vector<std::vector< std::vector<std::string> > > >(_killCriteria);
4848
_sprite = node["sprite"].as<int>(_sprite);
4949
_listOrder = node["listOrder"].as<int>(_listOrder);
5050
if (!_listOrder)
@@ -84,7 +84,7 @@ std::map<std::string, std::vector<int> > *RuleCommendations::getCriteria()
8484
* Get commendation award kill criteria
8585
* @return vecotr<string> Commendation kill criteria
8686
*/
87-
std::vector< std::vector<std::string> > *RuleCommendations::getKillCriteria()
87+
std::vector<std::vector<std::vector<std::string> > > *RuleCommendations::getKillCriteria()
8888
{
8989
return &_killCriteria;
9090
}

src/Ruleset/RuleCommendations.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class RuleCommendations
3131
{
3232
private:
3333
std::map<std::string, std::vector<int> > _criteria;
34-
std::vector< std::vector<std::string> > _killCriteria;
34+
std::vector<std::vector< std::vector<std::string> > > _killCriteria;
3535
std::string _description;
3636
int _listOrder;
3737
int _sprite;
@@ -51,7 +51,7 @@ class RuleCommendations
5151
/// Get commendation award criteria
5252
std::map<std::string, std::vector<int> > *getCriteria();
5353
/// Get commendation award kill related criteria
54-
std::vector< std::vector<std::string> > *getKillCriteria();
54+
std::vector<std::vector<std::vector<std::string> > > *getKillCriteria();
5555
/// Get sprite
5656
int getSprite() const;
5757

src/Savegame/SoldierDiary.cpp

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -434,49 +434,53 @@ bool SoldierDiary::manageCommendations(Ruleset *rules)
434434
}
435435
else if ((*j).first == "kills_with_criteria")
436436
{
437-
std::vector<std::vector<std::string> > *_killCriteriaList = (*i).second->getKillCriteria();
437+
// Vector of ORs, vector of ANDs, vector of DETAILs
438+
std::vector<std::vector<std::vector<std::string> > > *_killCriteriaList = (*i).second->getKillCriteria();
438439

439-
/// Add "original faction" to the SoldierDiaryKills class so we can track enemy kills
440-
/// Look to see if it's possible to convert the enum AlienState to a string when comparing OR convert the string from the ruleset to an enum AlienState
441-
442-
// Loop over the vector of vectors of items
443-
for (std::vector<std::vector<std::string> >::const_iterator listItem = _killCriteriaList->begin(); listItem != _killCriteriaList->end(); ++listItem)
440+
// Loop over the vector of ORs
441+
for (std::vector<std::vector<std::vector<std::string> > >::const_iterator iterOR = _killCriteriaList->begin(); iterOR != _killCriteriaList->end(); ++iterOR)
444442
{
445-
int count = 0; // Reset count
446-
// Loop over the vector of kills
447-
for (std::vector<SoldierDiaryKills*>::const_iterator singleKill = _killList.begin(); singleKill != _killList.end(); ++singleKill)
443+
// Loop over the vector of ANDs
444+
for (std::vector<std::vector<std::string> >::const_iterator listItem = iterOR->begin(); listItem != iterOR->end(); ++listItem)
448445
{
449-
bool foundMatch = true; // Reset bool
450-
// Loop over the vector of items
451-
for (std::vector<std::string>::const_iterator item = listItem->begin(); item != listItem->end(); ++item)
446+
int count = 0; // Reset count
447+
// Loop over through kills
448+
for (std::vector<SoldierDiaryKills*>::const_iterator singleKill = _killList.begin(); singleKill != _killList.end(); ++singleKill)
452449
{
453-
// See if we find no matches with any criteria. If so, break and try the next kill.
454-
if ( (*singleKill)->getAlienRank() != (*item) && (*singleKill)->getAlienRace() != (*item) &&
455-
(*singleKill)->getWeapon() != (*item) && (*singleKill)->getWeaponAmmo() != (*item) &&
456-
(*singleKill)->getAlienState() != (*item) && (*singleKill)->getAlienFaction() != (*item) )
450+
bool foundMatch = true; // Reset bool
451+
// Loop over the vector of DETAILs
452+
for (std::vector<std::string>::const_iterator detail = listItem->begin(); detail != listItem->end(); ++detail)
457453
{
458-
foundMatch = false;
459-
break;
454+
// See if we find no matches with any criteria. If so, break and try the next kill.
455+
if ( (*singleKill)->getAlienRank() != (*detail) && (*singleKill)->getAlienRace() != (*detail) &&
456+
(*singleKill)->getWeapon() != (*detail) && (*singleKill)->getWeaponAmmo() != (*detail) &&
457+
(*singleKill)->getAlienState() != (*detail) && (*singleKill)->getAlienFaction() != (*detail) )
458+
{
459+
foundMatch = false;
460+
break;
461+
}
460462
}
463+
// If all the DETAILs were matched in a singleKill, then increment count
464+
if (foundMatch) count++;
461465
}
462-
if (foundMatch) count++;
463-
}
464-
// If this single vector of items doesn't make the cut, do not award commendation
465-
if (count < (*j).second.at(_nextCommendationLevel[""]))
466-
{
467-
_awardCommendation = false;
468-
break;
466+
// If this single vector of DETAILS did not have a high enough kill count, do not award commendation for this AND vector but try the next OR vector
467+
if (count < (*j).second.at(_nextCommendationLevel[""]))
468+
{
469+
_awardCommendation = false;
470+
break;
471+
}
472+
// Break out of this AND vector for loop because a DETAIL vector failed
473+
if (!_awardCommendation) break;
469474
}
470-
}
471-
// Break out of this for loop as well
472-
if (!_awardCommendation) break;
473-
475+
// If one of the AND vectors worked, no need to check any other OR vectors
476+
if (_awardCommendation) break;
477+
}
474478
}
475479
}
476480
if (_awardCommendation)
477481
{
478-
// If we do not have modular medals, but are awarded a different medal
479-
// Its noun will be ""
482+
// If we do not have modular medals, but are awarded a different medal,
483+
// its noun will be ""
480484
if (_modularCommendations.empty())
481485
{
482486
_modularCommendations[""] = 0;

0 commit comments

Comments
 (0)