Add a time multiplier for AI levels

Differential Revision: https://code.wildfiregames.com/D1350
This was SVN commit r21423.
This commit is contained in:
mimo 2018-03-03 10:05:04 +00:00
parent a8a29271ce
commit 5b314fc0ac
9 changed files with 61 additions and 57 deletions

View file

@ -45,7 +45,7 @@ Cost.prototype.GetPopBonus = function()
Cost.prototype.GetBuildTime = function()
{
var cmpPlayer = QueryOwnerInterface(this.entity);
var buildTime = (+this.template.BuildTime) * cmpPlayer.cheatTimeMultiplier;
var buildTime = (+this.template.BuildTime) * cmpPlayer.GetTimeMultiplier();
return ApplyValueModificationsToEntity("Cost/BuildTime", buildTime, this.entity);
};

View file

@ -98,8 +98,7 @@ Pack.prototype.GetPackTime = function()
{
let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
return ApplyValueModificationsToEntity("Pack/Time", +this.template.Time, this.entity) *
cmpPlayer.GetCheatTimeMultiplier();
return ApplyValueModificationsToEntity("Pack/Time", +this.template.Time, this.entity) * cmpPlayer.GetTimeMultiplier();
};
Pack.prototype.GetElapsedTime = function()

View file

@ -64,6 +64,7 @@ Player.prototype.Init = function()
this.startCam = undefined;
this.controlAllUnits = false;
this.isAI = false;
this.timeMultiplier = 1;
this.gatherRateMultiplier = 1;
this.tradeRateMultiplier = 1;
this.cheatsEnabled = false;
@ -89,7 +90,7 @@ Player.prototype.Init = function()
this.resourceCount[res] = 300;
this.resourceNames[res] = Resources.GetResource(res).name;
this.tradingGoods.push({
"goods": res,
"goods": res,
"proba": 5 * (quotient + (+i < remainder ? 1 : 0))
});
}
@ -223,19 +224,14 @@ Player.prototype.GetBarterMultiplier = function()
return this.barterMultiplier;
};
Player.prototype.SetGatherRateMultiplier = function(value)
{
this.gatherRateMultiplier = value;
};
Player.prototype.GetGatherRateMultiplier = function()
{
return this.gatherRateMultiplier;
return this.gatherRateMultiplier / this.cheatTimeMultiplier;
};
Player.prototype.SetTradeRateMultiplier = function(value)
Player.prototype.GetTimeMultiplier = function()
{
this.tradeRateMultiplier = value;
return this.timeMultiplier * this.cheatTimeMultiplier;
};
Player.prototype.GetTradeRateMultiplier = function()
@ -248,6 +244,24 @@ Player.prototype.GetSpyCostMultiplier = function()
return this.spyCostMultiplier;
};
/**
* Setters currently used by the AI to set the difficulty level
*/
Player.prototype.SetGatherRateMultiplier = function(value)
{
this.gatherRateMultiplier = value;
};
Player.prototype.SetTimeMultiplier = function(value)
{
this.timeMultiplier = value;
};
Player.prototype.SetTradeRateMultiplier = function(value)
{
this.tradeRateMultiplier = value;
};
Player.prototype.GetPanelEntities = function()
{
return this.panelEntities;

View file

@ -191,9 +191,7 @@ ProductionQueue.prototype.GetTechnologiesList = function()
{
var tech = techList[i];
while (this.IsTechnologyResearchedOrInProgress(tech))
{
tech = superseded[tech];
}
techList[i] = tech;
}
@ -212,7 +210,7 @@ ProductionQueue.prototype.GetTechnologiesList = function()
let template = TechnologyTemplates.Get(tech);
if (template.top)
ret[i] = {"pair": true, "top": template.top, "bottom": template.bottom};
ret[i] = { "pair": true, "top": template.top, "bottom": template.bottom };
else
ret[i] = tech;
}
@ -237,14 +235,10 @@ ProductionQueue.prototype.IsTechnologyResearchedOrInProgress = function(tech)
let template = TechnologyTemplates.Get(tech);
if (template.top)
{
return (cmpTechnologyManager.IsTechnologyResearched(template.top) || cmpTechnologyManager.IsInProgress(template.top)
|| cmpTechnologyManager.IsTechnologyResearched(template.bottom) || cmpTechnologyManager.IsInProgress(template.bottom));
}
else
{
return (cmpTechnologyManager.IsTechnologyResearched(tech) || cmpTechnologyManager.IsInProgress(tech));
}
return cmpTechnologyManager.IsTechnologyResearched(template.top) || cmpTechnologyManager.IsInProgress(template.top) ||
cmpTechnologyManager.IsTechnologyResearched(template.bottom) || cmpTechnologyManager.IsInProgress(template.bottom);
return cmpTechnologyManager.IsTechnologyResearched(tech) || cmpTechnologyManager.IsInProgress(tech);
};
/*
@ -300,7 +294,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
totalCosts[res] = Math.floor(count * costs[res]);
}
var population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, cmpPlayer.GetPlayerID(), template);
var population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, cmpPlayer.GetPlayerID(), template);
// TrySubtractResources should report error to player (they ran out of resources)
if (!cmpPlayer.TrySubtractResources(totalCosts))
@ -329,7 +323,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
// Call the related trigger event
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
cmpTrigger.CallEvent("TrainingQueued", {"playerid": cmpPlayer.GetPlayerID(), "unitTemplate": templateName, "count": count, "metadata": metadata, "trainerEntity": this.entity});
cmpTrigger.CallEvent("TrainingQueued", { "playerid": cmpPlayer.GetPlayerID(), "unitTemplate": templateName, "count": count, "metadata": metadata, "trainerEntity": this.entity });
}
else if (type == "technology")
{
@ -348,7 +342,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
let template = TechnologyTemplates.Get(templateName);
let techCostMultiplier = this.GetTechCostMultiplier();
let time = techCostMultiplier.time * template.researchTime * cmpPlayer.GetCheatTimeMultiplier();
let time = techCostMultiplier.time * template.researchTime * cmpPlayer.GetTimeMultiplier();
let cost = {};
for (let res in template.cost)
@ -378,7 +372,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
// Call the related trigger event
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
cmpTrigger.CallEvent("ResearchQueued", {"playerid": cmpPlayer.GetPlayerID(), "technologyTemplate": templateName, "researcherEntity": this.entity});
cmpTrigger.CallEvent("ResearchQueued", { "playerid": cmpPlayer.GetPlayerID(), "technologyTemplate": templateName, "researcherEntity": this.entity });
}
else
{
@ -397,7 +391,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
}
else
{
var notification = {"players": [cmpPlayer.GetPlayerID()], "message": markForTranslation("The production queue is full."), "translateMessage": true };
var notification = { "players": [cmpPlayer.GetPlayerID()], "message": markForTranslation("The production queue is full."), "translateMessage": true };
var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
cmpGUIInterface.PushNotification(notification);
}
@ -410,10 +404,9 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
ProductionQueue.prototype.RemoveBatch = function(id)
{
// Destroy any cached entities (those which didn't spawn for some reason)
for (var i = 0; i < this.entityCache.length; ++i)
{
Engine.DestroyEntity(this.entityCache[i]);
}
for (let ent of this.entityCache)
Engine.DestroyEntity(ent);
this.entityCache = [];
for (var i = 0; i < this.queue.length; ++i)
@ -486,7 +479,7 @@ ProductionQueue.prototype.GetQueue = function()
"technologyTemplate": item.technologyTemplate,
"count": item.count,
"neededSlots": item.neededSlots,
"progress": 1 - ( item.timeRemaining / (item.timeTotal || 1) ),
"progress": 1 - (item.timeRemaining / (item.timeTotal || 1)),
"timeRemaining": item.timeRemaining,
"metadata": item.metadata,
});
@ -517,7 +510,7 @@ ProductionQueue.prototype.GetBatchTime = function(batchSize)
var batchTimeModifier = ApplyValueModificationsToEntity("ProductionQueue/BatchTimeModifier", +this.template.BatchTimeModifier, this.entity);
// TODO: work out what equation we should use here.
return Math.pow(batchSize, batchTimeModifier) * cmpPlayer.GetCheatTimeMultiplier();
return Math.pow(batchSize, batchTimeModifier) * cmpPlayer.GetTimeMultiplier();
};
ProductionQueue.prototype.OnOwnershipChanged = function(msg)
@ -588,7 +581,7 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata)
{
var unitCategory = cmpTrainingRestrictions.GetCategory();
var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits);
cmpPlayerEntityLimits.ChangeCount(unitCategory,-1);
cmpPlayerEntityLimits.ChangeCount(unitCategory, -1);
}
}
}
@ -701,7 +694,7 @@ ProductionQueue.prototype.ProgressTimeout = function(data)
{
// If something change population cost
var template = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate(item.unitTemplate);
item.population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, item.player, template);
item.population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, item.player, template);
// Batch's training hasn't started yet.
// Try to reserve the necessary population slots
@ -729,7 +722,7 @@ ProductionQueue.prototype.ProgressTimeout = function(data)
item.productionStarted = true;
if (item.unitTemplate)
Engine.PostMessage(this.entity, MT_TrainingStarted, {"entity": this.entity});
Engine.PostMessage(this.entity, MT_TrainingStarted, { "entity": this.entity });
}
// If we won't finish the batch now, just update its timer

View file

@ -69,9 +69,7 @@ ResourceGatherer.prototype.GetCarryingStatus = function()
ResourceGatherer.prototype.GiveResources = function(resources)
{
for (let resource of resources)
{
this.carrying[resource.type] = +(resource.amount);
}
Engine.PostMessage(this.entity, MT_ResourceCarryingChanged, { "to": this.GetCarryingStatus() });
};
@ -98,8 +96,8 @@ ResourceGatherer.prototype.GetLastCarriedType = function()
{
if (this.lastCarriedType && this.lastCarriedType.generic in this.carrying)
return this.lastCarriedType;
else
return undefined;
return undefined;
};
// Since this code is very performancecritical and applying technologies quite slow, cache it.
@ -179,7 +177,7 @@ ResourceGatherer.prototype.TryInstantGather = function(target)
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
if (cmpTrigger && cmpPlayer)
cmpTrigger.CallEvent("TreasureCollected", {"player": cmpPlayer.GetPlayerID(), "type": type.specific, "amount": status.amount });
cmpTrigger.CallEvent("TreasureCollected", { "player": cmpPlayer.GetPlayerID(), "type": type.specific, "amount": status.amount });
return true;
};
@ -248,10 +246,6 @@ ResourceGatherer.prototype.GetTargetGatherRate = function(target)
if (rate == 0 && type.generic)
rate = this.GetGatherRate(type.generic);
let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
let cheatMultiplier = cmpPlayer ? cmpPlayer.GetCheatTimeMultiplier() : 1;
rate = rate / cheatMultiplier;
if ("Mirages" in cmpResourceSupply)
return rate;

View file

@ -277,7 +277,7 @@ Upgrade.prototype.GetUpgradeTime = function(templateArg)
let cmpPlayer = QueryPlayerIDInterface(this.owner, IID_Player);
return ApplyValueModificationsToEntity("Upgrade/Time", +this.template[choice].Time, this.entity) *
cmpPlayer.GetCheatTimeMultiplier();
cmpPlayer.GetTimeMultiplier();
};
Upgrade.prototype.GetElapsedTime = function()

View file

@ -33,7 +33,7 @@ AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
});
AddMock(11, IID_Player, {
"GetCheatTimeMultiplier": () => 1
"GetTimeMultiplier": () => 1
});
AddMock(ent, IID_Sound, {
@ -127,11 +127,11 @@ TS_ASSERT_EQUALS(cmpPack.GetElapsedTime(), 400);
TS_ASSERT_EQUALS(cmpPack.timer, 7);
TS_ASSERT(timerActivated);
// Cancel
// Cancel
cmpPack.CancelPack();
TS_ASSERT(!cmpPack.IsPacking());
TS_ASSERT_EQUALS(cmpPack.GetElapsedTime(), 0)
TS_ASSERT_EQUALS(cmpPack.GetElapsedTime(), 0);
TS_ASSERT_EQUALS(cmpPack.GetProgress(), 0);
TS_ASSERT_EQUALS(cmpPack.timer, undefined);
TS_ASSERT(!timerActivated);

View file

@ -63,14 +63,14 @@ let templateTechModifications = {
};
let entityTechModifications = {
"without": {
'Upgrade/Cost/stone': { 20: { "origValue": 100, "newValue": 100 } },
'Upgrade/Cost/wood': { 20: { "origValue": 50, "newValue": 50 } },
'Upgrade/Time': { 20: { "origValue": 100, "newValue": 100 } }
'Upgrade/Cost/stone': { "20": { "origValue": 100, "newValue": 100 } },
'Upgrade/Cost/wood': { "20": { "origValue": 50, "newValue": 50 } },
'Upgrade/Time': { "20": { "origValue": 100, "newValue": 100 } }
},
"with": {
'Upgrade/Cost/stone': { 20: { "origValue": 100, "newValue": 160 } },
'Upgrade/Cost/wood': { 20: { "origValue": 50, "newValue": 25 } },
'Upgrade/Time': { 20: { "origValue": 100, "newValue": 90 } }
'Upgrade/Cost/stone': { "20": { "origValue": 100, "newValue": 160 } },
'Upgrade/Cost/wood': { "20": { "origValue": 50, "newValue": 25 } },
'Upgrade/Time': { "20": { "origValue": 100, "newValue": 90 } }
}
};
@ -93,7 +93,7 @@ AddMock(SYSTEM_ENTITY, IID_Timer, {
AddMock(10, IID_Player, {
"AddResources": () => {}, // Called in components/Upgrade.js::CancelUpgrade().
"GetPlayerID": () => playerID, // Called in helpers/Player.js::QueryOwnerInterface() (and several times below).
"GetCheatTimeMultiplier": () => 1.0, // Called in components/Upgrade.js::GetUpgradeTime().
"GetTimeMultiplier": () => 1.0, // Called in components/Upgrade.js::GetUpgradeTime().
"TrySubtractResources": () => true // Called in components/Upgrade.js::Upgrade().
});
AddMock(10, IID_TechnologyManager, {

View file

@ -42,7 +42,10 @@ function InitGame(settings)
}
// Sandbox, Very Easy, Easy, Medium, Hard, Very Hard
// rate apply on resource stockpiling as gathering and trading
// time apply on building, upgrading, packing, training and technologies
let rate = [ 0.42, 0.56, 0.75, 1.00, 1.25, 1.56 ];
let time = [ 1.30, 1.15, 1.00, 1.00, 1.00, 1.00 ];
let cmpAIManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AIManager);
for (let i = 0; i < settings.PlayerData.length; ++i)
{
@ -56,6 +59,7 @@ function InitGame(settings)
AIDiff = Math.min(AIDiff, rate.length - 1);
cmpPlayer.SetGatherRateMultiplier(rate[AIDiff]);
cmpPlayer.SetTradeRateMultiplier(rate[AIDiff]);
cmpPlayer.SetTimeMultiplier(time[AIDiff]);
}
if (settings.PopulationCap)
cmpPlayer.SetMaxPopulation(settings.PopulationCap);