Changeset View
Standalone View
binaries/data/mods/public/maps/scripts/CaptureTheFlag.js
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
Trigger.prototype.CheckCaptureTheFlagVictory = function(data) | |||||
{ | |||||
let cmpIdentity = Engine.QueryInterface(data.entity, IID_Identity); | |||||
if (!cmpIdentity || !cmpIdentity.HasClass("Flag") || data.from == -1) | |||||
return; | |||||
if (data.from != 0) | |||||
--this.playerFlagsCount[data.from]; | |||||
++this.playerFlagsCount[data.to]; | |||||
this.CheckCountdown(); | |||||
}; | |||||
/** | |||||
* Check if an individual player or a team has acquired all the flags | |||||
* Also check if the countdown needs to be stopped if a player/team no longer has all the flags | |||||
*/ | |||||
bb: `GetTemplate` and `GetCurrentTemplateName` can return `null` so should be checked upon. I guess… | |||||
Trigger.prototype.CheckCountdown = function() | |||||
{ | |||||
for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) | |||||
{ | |||||
let playerAndAllies = QueryPlayerIDInterface(playerID).GetMutualAllies(); | |||||
let teamflagsOwned = 0; | |||||
for (let ally of playerAndAllies) | |||||
teamflagsOwned += this.playerFlagsCount[ally]; | |||||
if (teamflagsOwned == this.flags.length - 1) | |||||
{ | |||||
let data = { "entity": this.flags[playerID], "to": playerAndAllies }; | |||||
this.StartCountdown(data, playerAndAllies.length > 1); | |||||
return; | |||||
} | |||||
Done Inline Actionscould be inlined (perhaps split over lines then) bb: could be inlined (perhaps split over lines then) | |||||
Not Done Inline ActionsOK. Sandarac: OK. | |||||
} | |||||
this.DeleteCaptureTheFlagVictoryMessages(); | |||||
}; | |||||
Trigger.prototype.DeleteCaptureTheFlagVictoryMessages = function() | |||||
{ | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
Not Done Inline ActionsAs stated before this could become an optional template entry in the armour/damagereveiver component. (Pls reply on comments you do not agree with/don't understand etc. so I won't repeat myself.) bb: As stated before this could become an optional template entry in the armour/damagereveiver… | |||||
Not Done Inline ActionsYou should know that modifying Armour.js like this is out of the scope for a diff like this, so no. Sandarac: You should know that modifying Armour.js like this is out of the scope for a diff like this, so… | |||||
Not Done Inline ActionsI agree with all three sentences :P elexis: I agree with all three sentences :P | |||||
for (let ent in this.flagsVictoryMessages) | |||||
{ | |||||
cmpGuiInterface.DeleteTimeNotification(this.flagsVictoryMessages[ent].ownMessage); | |||||
cmpGuiInterface.DeleteTimeNotification(this.flagsVictoryMessages[ent].otherMessage); | |||||
cmpTimer.CancelTimer(this.flagsVictoryTimers[ent]); | |||||
} | |||||
}; | |||||
Trigger.prototype.StartCountdown = function(data, isTeam) | |||||
{ | |||||
let timer = this.flagsVictoryTimers[data.entity]; | |||||
let messages = this.flagsVictoryMessages[data.entity] || {}; | |||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||
Done Inline ActionsThis variable is strictly unneeded so can be removed bb: This variable is strictly unneeded so can be removed | |||||
Not Done Inline ActionsOK Sandarac: OK | |||||
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
if (timer) | |||||
{ | |||||
Done Inline Actionsgaia count won't be correct (it is not a problem in other code but just ugly). This also needs change around L36, so gaia is put at 0. bb: gaia count won't be correct (it is not a problem in other code but just ugly). This also needs… | |||||
Not Done Inline ActionsYes, you are right, I forgot to account for gaia (especially for cases like when a player is defeated and the flags return to gaia ownership). Sandarac: Yes, you are right, I forgot to account for gaia (especially for cases like when a player is… | |||||
cmpTimer.CancelTimer(timer); | |||||
cmpGuiInterface.DeleteTimeNotification(messages.ownMessage); | |||||
cmpGuiInterface.DeleteTimeNotification(messages.otherMessage); | |||||
} | |||||
let players = [-1]; | |||||
for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) | |||||
{ | |||||
let cmpPlayer = QueryPlayerIDInterface(playerID); | |||||
if (cmpPlayer.GetState() == "won") | |||||
return; | |||||
if (data.to.indexOf(playerID) == -1) | |||||
players.push(playerID); | |||||
} | |||||
let cmpPlayer = QueryOwnerInterface(data.entity, IID_Player); | |||||
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); | |||||
let captureTheFlagDuration = cmpEndGameManager.GetGameTypeSettings().captureTheFlagDuration || 0; | |||||
messages.otherMessage = cmpGuiInterface.AddTimeNotification({ | |||||
"message": isTeam ? markForTranslation("%(player)s's team has captured all of the flags. They will have won in %(time)s") : | |||||
markForTranslation("%(player)s has captured all of the flags. They will have won in %(time)s"), | |||||
"players": players, | |||||
"parameters": { | |||||
"player": cmpPlayer.GetName() | |||||
}, | |||||
"translateMessage": true, | |||||
"translateParameters": [], | |||||
}, captureTheFlagDuration); | |||||
messages.ownMessage = cmpGuiInterface.AddTimeNotification({ | |||||
"message": isTeam ? markForTranslation("Your team has captured all of the flags. You will have won in %(time)s") : | |||||
markForTranslation("You have captured all of the flags. You will have won in %(time)s"), | |||||
"players": data.to, | |||||
"translateMessage": true, | |||||
}, captureTheFlagDuration); | |||||
Not Done Inline ActionsIs this also send to teammates? bb: Is this also send to teammates? | |||||
Not Done Inline ActionsYes. Sandarac: Yes. | |||||
timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, | |||||
"MarkPlayerAsWon", captureTheFlagDuration, data.to[0]); | |||||
this.flagsVictoryTimers[data.entity] = timer; | |||||
this.flagsVictoryMessages[data.entity] = messages; | |||||
}; | |||||
Trigger.prototype.InitflagsGame = function() | |||||
{ | |||||
// Attempt to spawn one flag per player randomly in neutral territory | |||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | |||||
Done Inline ActionsInit may go on top of the file bb: Init may go on top of the file | |||||
Not Done Inline ActionsOK. Sandarac: OK. | |||||
let cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager); | |||||
let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); | |||||
let validSpawnPoint = entity => { | |||||
let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); | |||||
let cmpPosition = Engine.QueryInterface(entity, IID_Position); | |||||
if (!cmpIdentity || !cmpPosition || !cmpPosition.IsInWorld()) | |||||
Not Done Inline ActionsUsing this.flagsVictoryMessages[data.entity] is in function above seems cleaner. I guess messages variable can be removed then (changing some lines below too)? bb: Using `this.flagsVictoryMessages[data.entity]` is in function above seems cleaner. I guess… | |||||
Not Done Inline ActionsI don't think shoving this.flagsVictoryMessages[data.entity] into the code multiple times will make it any cleaner or more readable, so I think it would be best to keep the messages variable. Sandarac: I don't think shoving `this.flagsVictoryMessages[data.entity]` into the code multiple times… | |||||
return false; | |||||
let pos = cmpPosition.GetPosition(); | |||||
if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z) || | |||||
cmpTerritoryManager.GetOwner(pos.x, pos.z) != 0) | |||||
return false; | |||||
return true; | |||||
}; | |||||
let gaiaEntities = cmpRangeManager.GetEntitiesByPlayer(0).filter(entity => validSpawnPoint(entity)); | |||||
if (!gaiaEntities.length) | |||||
{ | |||||
Not Done Inline ActionsI guess this means on an emtpy map there won't be any spawn points, but there is neutral territory, so there are valid points imo. bb: I guess this means on an emtpy map there won't be any spawn points, but there is neutral… | |||||
Not Done Inline ActionsOK. Sandarac: OK. | |||||
Not Done Inline ActionsThe missing bird check is a good observeration, he has to check for the absence of UnitMotionFlying then. We actually have to test for entities as we can assume that all entities (that aren't actors) can be reached by the player, whereas we distinguish islands from impassable mountains (for example with a pathfinding check) - unless you have an idea we didn't think of. elexis: The missing bird check is a good observeration, he has to check for the absence of… | |||||
error("No valid flag spawn points on map"); | |||||
return; | |||||
} | |||||
Not Done Inline ActionsThese messages are also send when captureTheFlagDuration==0, but invisible then so ok. bb: These messages are also send when captureTheFlagDuration==0, but invisible then so ok. | |||||
for (let i = 1; i < TriggerHelper.GetNumberOfPlayers(); ++i) | |||||
Done Inline ActionsWrong intentation. I suggest using: "message": isTeam ? Translate() : Translate(), bb: Wrong intentation.
I suggest using:
```
"message": isTeam ?
Translate() :
Translate… | |||||
{ | |||||
this.flags[i] = TriggerHelper.SpawnUnits(pickRandom(gaiaEntities), "other/special_flag", 1, 0)[0]; | |||||
this.playerFlagsCount[i] = 0; | |||||
let cmpDamageReceiver = Engine.QueryInterface(this.flags[i], IID_DamageReceiver); | |||||
Not Done Inline ActionsFlags spawn inside entity? bb: Flags spawn inside entity? | |||||
Not Done Inline ActionsWhen picking a spawn point, TriggerHelper.SpawnUnits uses the same function as the ProductionQueue component in order to find available space around the source entity's footprint (cmpFootprint.PickSpawnPoint), so they spawn around the entity. Sandarac: When picking a spawn point, `TriggerHelper.SpawnUnits` uses the same function as the… | |||||
Not Done Inline ActionsAh right, flags still will most of the time spawn in the middle of some forest. But that could be fixed with searching for empty tiles too. bb: Ah right, flags still will most of the time spawn in the middle of some forest. But that could… | |||||
cmpDamageReceiver.SetInvulnerability(true); | |||||
Done Inline Actionstrailing comma bb: trailing comma | |||||
} | |||||
}; | |||||
Not Done Inline ActionsIMO this could get an damageReceiver optional template element bb: IMO this could get an damageReceiver optional template element | |||||
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | |||||
cmpTrigger.flags = []; | |||||
Not Done Inline ActionsPerhaps it would be better to search for empty neutral tiles, instead of looking for gaia entity's. I guess you need to adapt the territoryManager for this (f.e. make some new function returning all tiles owned by a player) bb: Perhaps it would be better to search for empty neutral tiles, instead of looking for gaia… | |||||
Not Done Inline ActionsYes, and that probably should be handled in a different diff. Sandarac: Yes, and that probably should be handled in a different diff. | |||||
Not Done Inline ActionsWell this would likely solve the edgy cases like birds, flags in trees and empty maps and I believe these things should be done in one go, otherwise we end up with some partially broken gamemode, others might think else though. bb: Well this would likely solve the edgy cases like birds, flags in trees and empty maps and I… | |||||
Done Inline ActionsSame as above bb: Same as above | |||||
cmpTrigger.playerFlagsCount = []; | |||||
cmpTrigger.flagsVictoryTimers = {}; | |||||
Done Inline Actionsanother , bb: another , | |||||
cmpTrigger.flagsVictoryMessages = {}; | |||||
cmpTrigger.DoAfterDelay(0, "InitflagsGame", {}); | |||||
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckCaptureTheFlagVictory", { "enabled": true }); | |||||
cmpTrigger.RegisterTrigger("OnDiplomacyChanged", "CheckCountdown", { "enabled": true }); |
GetTemplate and GetCurrentTemplateName can return null so should be checked upon. I guess it's best to split the if then...