Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/maps/random/rmgen-common/player.js
Show All 17 Lines | var g_PlayerBaseFunctions = [ | ||||
// Possibly mark player class first here and use it afterwards | // Possibly mark player class first here and use it afterwards | ||||
"CityPatch", | "CityPatch", | ||||
// Create the largest and most important entities first | // Create the largest and most important entities first | ||||
"Trees", | "Trees", | ||||
"Mines", | "Mines", | ||||
"Treasures", | "Treasures", | ||||
"Berries", | "Berries", | ||||
"Chicken", | "Chicken", | ||||
"Decoratives" | "Decoratives", | ||||
"NearbyResources" | |||||
]; | ]; | ||||
function isNomad() | function isNomad() | ||||
{ | { | ||||
return !!g_MapSettings.Nomad; | return !!g_MapSettings.Nomad; | ||||
} | } | ||||
function getNumPlayers() | function getNumPlayers() | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Places the civic center and starting resources for all given players. | * Places the civic center and starting resources for all given players. | ||||
*/ | */ | ||||
function placePlayerBases(playerBaseArgs) | function placePlayerBases(playerBaseArgs) | ||||
{ | { | ||||
g_Map.log("Creating playerbases"); | g_Map.log("Creating playerbases"); | ||||
let [playerIDs, playerPosition] = playerBaseArgs.PlayerPlacement; | let [playerIDs, playerPosition] = playerBaseArgs.PlayerPlacement; | ||||
let playersResourcesCount = getPlayersResourceCount(playerBaseArgs); | |||||
for (let i = 0; i < getNumPlayers(); ++i) | for (let i = 0; i < getNumPlayers(); ++i) | ||||
{ | { | ||||
playerBaseArgs.playerID = playerIDs[i]; | playerBaseArgs.playerID = playerIDs[i]; | ||||
playerBaseArgs.playerPosition = playerPosition[i]; | playerBaseArgs.playerPosition = playerPosition[i]; | ||||
if (playerBaseArgs.Balance && playerBaseArgs.Balance != "none") | |||||
playerBaseArgs.NearbyResources.foodAmount = playersResourcesCount[i]; | |||||
placePlayerBase(playerBaseArgs); | placePlayerBase(playerBaseArgs); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Places the civic center and starting resources. | * Places the civic center and starting resources. | ||||
*/ | */ | ||||
function placePlayerBase(playerBaseArgs) | function placePlayerBase(playerBaseArgs) | ||||
▲ Show 20 Lines • Show All 281 Lines • ▼ Show 20 Lines | for (let x = 0; x < get("maxTries", 30); ++x) | ||||
} | } | ||||
} | } | ||||
if (!success) | if (!success) | ||||
// Don't warn since the decoratives are not important | // Don't warn since the decoratives are not important | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
function placePlayerBaseNearbyResources(args) | |||||
{ | |||||
let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); | |||||
let area = createArea(new DiskPlacer(get("radius", 30), basePosition), null, null); | |||||
let place = function(type, amount) { | |||||
let group = new SimpleGroup( | |||||
[new SimpleObject(type, amount, amount, 0, 4)], | |||||
true, args.foodTileClass | |||||
); | |||||
createObjectGroupsByAreas(group, 0, args.foodConstraints, 1, 300, [area]); | |||||
}; | |||||
let getFoodAmount = function(template) { | |||||
return GetBaseTemplateDataValue(Engine.GetTemplate(template), "ResourceSupply/Max"); | |||||
}; | |||||
let remainingFood = get("foodAmount", 0); | |||||
let animals = args.animals; | |||||
animals.sort((a, b) => getFoodAmount(a.template) > getFoodAmount(b.template)); | |||||
while (remainingFood > 0) | |||||
{ | |||||
if (remainingFood <= 700) | |||||
{ | |||||
// We want to get as close to 0 as possible to end food placement. | |||||
// In low quantities of food, berries are less useful, so we generate hunt everytime. | |||||
let smallestAnimal = animals[0].template; | |||||
let amount = remainingFood / getFoodAmount(smallestAnimal); | |||||
place(smallestAnimal, amount); | |||||
remainingFood = 0; | |||||
} | |||||
else | |||||
{ | |||||
if (randBool(0.5 * get("huntBerryRatio", 1))) | |||||
{ | |||||
let currentAnimal = pickRandom(animals).template; | |||||
let currentAnimalFood = getFoodAmount(currentAnimal); | |||||
let maxAmount = remainingFood / currentAnimalFood; | |||||
let desiredAmount = randIntInclusive(5, 7); | |||||
desiredAmount = Math.max(desiredAmount, desiredAmount * 100 / currentAnimalFood); | |||||
let amount = Math.min(maxAmount, desiredAmount); | |||||
remainingFood -= amount * currentAnimalFood; | |||||
place(currentAnimal, amount); | |||||
} | |||||
else | |||||
{ | |||||
let mainBerryFood = getFoodAmount(args.berries.template); | |||||
let amount = Math.min(remainingFood, 1200) / mainBerryFood; | |||||
remainingFood -= amount * mainBerryFood; | |||||
place(args.berries.template, amount); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
function placePlayersNomad(playerClass, constraints) | function placePlayersNomad(playerClass, constraints) | ||||
{ | { | ||||
if (!isNomad()) | if (!isNomad()) | ||||
return undefined; | return undefined; | ||||
g_Map.log("Placing nomad starting units"); | g_Map.log("Placing nomad starting units"); | ||||
let distance = scaleByMapSize(60, 240); | let distance = scaleByMapSize(60, 240); | ||||
▲ Show 20 Lines • Show All 386 Lines • ▼ Show 20 Lines | if (bestShift) | ||||
let newPlayerIDs = []; | let newPlayerIDs = []; | ||||
for (let i = 0; i < playerIDs.length; ++i) | for (let i = 0; i < playerIDs.length; ++i) | ||||
newPlayerIDs.push(playerIDs[(i + bestShift) % playerIDs.length]); | newPlayerIDs.push(playerIDs[(i + bestShift) % playerIDs.length]); | ||||
playerIDs = newPlayerIDs; | playerIDs = newPlayerIDs; | ||||
} | } | ||||
return [playerIDs, startLocations]; | return [playerIDs, startLocations]; | ||||
} | } | ||||
function getPlayersResourceCount(playerBaseArgs) | |||||
{ | |||||
let playerIDs = playerBaseArgs.PlayerPlacement[0]; | |||||
if (!playerBaseArgs.NearbyResources) | |||||
return playerIDs.map(playerID => 0); | |||||
let huntablesFoodCount = playerBaseArgs.NearbyResources.animals.map( | |||||
animal => GetBaseTemplateDataValue(Engine.GetTemplate(animal.template), "ResourceSupply/Max") | |||||
); | |||||
let maxHuntableFoodCount = Math.max.apply(Math, huntablesFoodCount); | |||||
if (playerBaseArgs.Balance == "player") | |||||
{ | |||||
let totalFood = randIntInclusive(0, 20) * 100 * playerBaseArgs.NearbyResources.foodAvailability; | |||||
totalFood += maxHuntableFoodCount * 5; | |||||
if (randBool(0.2)) | |||||
totalFood = 0; | |||||
return playerIDs.map(playerID => totalFood); | |||||
} | |||||
if (playerBaseArgs.Balance == "team") | |||||
{ | |||||
// TODO: rewrite this part using partitionPlayers (I missed it) | |||||
let averageFood = 1000 * playerBaseArgs.NearbyResources.foodAvailability + maxHuntableFoodCount * 5; | |||||
let sortedPlayers = sortPlayers(playerIDs); | |||||
let distribution = []; | |||||
let currentTeam = -1; | |||||
let currentTeamDistribution = []; | |||||
for (let i = 0; i < numPlayers; ++i) | |||||
{ | |||||
let playerTeam = getPlayerTeam(sortedPlayers[i]); | |||||
if (playerTeam == -1) | |||||
{ | |||||
distribution[sortedPlayers[i]] = averageFood; | |||||
continue; | |||||
} | |||||
if (playerTeam != currentTeam) | |||||
{ | |||||
currentTeam = playerTeam; | |||||
// Find team size | |||||
let teamSize = 1; | |||||
for (let j = i + 1; j < numPlayers && getPlayerTeam(sortedPlayers[j]) == currentTeam; ++j, ++teamSize); | |||||
lyv: D4670 moves over `getTeams` which can be used instead.
`getPlayerTeam` would return `-1` for… | |||||
// Assign resources to players in the team | |||||
let remainingFood = teamSize * averageFood; | |||||
for (let n = teamSize; n > 0; --n) | |||||
{ | |||||
if (n == 1) | |||||
lyvUnsubmitted Not Done Inline ActionsYou can move this block outside the loop and remove the condition. Something like this. for (let i = 0; i < teamSize - 1; ++i) { let remainingAverage = averageFood; // or remainingFood / n, undecided for now let deviation = randFloat(-1, 1) * remainingAverage / 2; let playerFood = remainingAverage + deviation; // Round to closest 100 playerFood = 100 * Math.round(playerFood / 100); if (playerFood > remainingFood) playerFood = remainingFood; if (playerFood <= 700) playerFood = 0; remainingFood -= playerFood; currentTeamDistribution.push(playerFood); } currentTeamDistribution.push(remainingFood); lyv: You can move this block outside the loop and remove the condition. Something like this.
```… | |||||
{ | |||||
currentTeamDistribution.push(remainingFood); | |||||
continue; | |||||
} | |||||
let remainingAverage = averageFood; // or remainingFood / n, undecided for now | |||||
let deviation = randFloat(-1, 1) * remainingAverage / 2; | |||||
let playerFood = remainingAverage + deviation; | |||||
// Round to closest 100 | |||||
playerFood = 100 * Math.round(playerFood / 100); | |||||
if (playerFood > remainingFood) | |||||
playerFood = remainingFood; | |||||
if (playerFood <= 700) | |||||
playerFood = 0; | |||||
remainingFood -= playerFood; | |||||
currentTeamDistribution.push(playerFood); | |||||
} | |||||
} | |||||
distribution[sortedPlayers[i]] = currentTeamDistribution.pop(); | |||||
} | |||||
return playerIDs.map(playerID => distribution[playerID]); | |||||
} | |||||
return playerIDs.map(playerID => 0); | |||||
} |
Wildfire Games · Phabricator
D4670 moves over getTeams which can be used instead.
getPlayerTeam would return -1 for all players with no teams.