Line data Source code
1 0 : PETRA.TrainingPlan = function(gameState, type, metadata, number = 1, maxMerge = 5) 2 : { 3 0 : if (!PETRA.QueuePlan.call(this, gameState, type, metadata)) 4 : { 5 0 : API3.warn(" Plan training " + type + " canceled"); 6 0 : return false; 7 : } 8 : 9 : // Refine the estimated cost and add pop cost 10 0 : let trainers = this.getBestTrainers(gameState); 11 0 : let trainer = trainers ? trainers[0] : undefined; 12 0 : this.cost = new API3.Resources(this.template.cost(trainer), +this.template._template.Cost.Population); 13 : 14 0 : this.category = "unit"; 15 0 : this.number = number; 16 0 : this.maxMerge = maxMerge; 17 : 18 0 : return true; 19 : }; 20 : 21 0 : PETRA.TrainingPlan.prototype = Object.create(PETRA.QueuePlan.prototype); 22 : 23 0 : PETRA.TrainingPlan.prototype.canStart = function(gameState) 24 : { 25 0 : this.trainers = this.getBestTrainers(gameState); 26 0 : if (!this.trainers) 27 0 : return false; 28 0 : this.cost = new API3.Resources(this.template.cost(this.trainers[0]), +this.template._template.Cost.Population); 29 0 : return true; 30 : }; 31 : 32 0 : PETRA.TrainingPlan.prototype.getBestTrainers = function(gameState) 33 : { 34 0 : if (this.metadata && this.metadata.trainer) 35 : { 36 0 : let trainer = gameState.getEntityById(this.metadata.trainer); 37 0 : if (trainer) 38 0 : return [trainer]; 39 : } 40 : 41 0 : let allTrainers = gameState.findTrainers(this.type); 42 0 : if (this.metadata && this.metadata.sea) 43 0 : allTrainers = allTrainers.filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea)); 44 0 : if (this.metadata && this.metadata.base) 45 0 : allTrainers = allTrainers.filter(API3.Filters.byMetadata(PlayerID, "base", this.metadata.base)); 46 0 : if (!allTrainers || !allTrainers.hasEntities()) 47 0 : return undefined; 48 : 49 : // Keep only trainers with smallest cost 50 0 : let costMin = Math.min(); 51 : let trainers; 52 0 : for (let ent of allTrainers.values()) 53 : { 54 0 : let cost = this.template.costSum(ent); 55 0 : if (cost === costMin) 56 0 : trainers.push(ent); 57 0 : else if (cost < costMin) 58 : { 59 0 : costMin = cost; 60 0 : trainers = [ent]; 61 : } 62 : } 63 0 : return trainers; 64 : }; 65 : 66 0 : PETRA.TrainingPlan.prototype.start = function(gameState) 67 : { 68 0 : if (this.metadata && this.metadata.trainer) 69 : { 70 0 : let metadata = {}; 71 0 : for (let key in this.metadata) 72 0 : if (key !== "trainer") 73 0 : metadata[key] = this.metadata[key]; 74 0 : this.metadata = metadata; 75 : } 76 : 77 0 : if (this.trainers.length > 1) 78 : { 79 : let wantedIndex; 80 0 : if (this.metadata && this.metadata.index) 81 0 : wantedIndex = this.metadata.index; 82 0 : const workerUnit = this.metadata && this.metadata.role && this.metadata.role === PETRA.Worker.ROLE_WORKER; 83 0 : let supportUnit = this.template.hasClass("Support"); 84 0 : this.trainers.sort(function(a, b) { 85 : // Prefer training buildings with short queues 86 0 : let aa = a.trainingQueueTime(); 87 0 : let bb = b.trainingQueueTime(); 88 : // Give priority to support units in the cc 89 0 : if (a.hasClass("Civic") && !supportUnit) 90 0 : aa += 10; 91 0 : if (b.hasClass("Civic") && !supportUnit) 92 0 : bb += 10; 93 : // And support units should not be too near to dangerous place 94 0 : if (supportUnit) 95 : { 96 0 : if (gameState.ai.HQ.isNearInvadingArmy(a.position())) 97 0 : aa += 50; 98 0 : if (gameState.ai.HQ.isNearInvadingArmy(b.position())) 99 0 : bb += 50; 100 : } 101 : // Give also priority to buildings with the right accessibility 102 0 : let aBase = a.getMetadata(PlayerID, "base"); 103 0 : let bBase = b.getMetadata(PlayerID, "base"); 104 0 : if (wantedIndex) 105 : { 106 0 : if (!aBase || gameState.ai.HQ.getBaseByID(aBase).accessIndex != wantedIndex) 107 0 : aa += 30; 108 0 : if (!bBase || gameState.ai.HQ.getBaseByID(bBase).accessIndex != wantedIndex) 109 0 : bb += 30; 110 : } 111 : // Then, if workers, small preference for bases with less workers 112 0 : if (workerUnit && aBase && bBase && aBase != bBase) 113 : { 114 0 : let apop = gameState.ai.HQ.getBaseByID(aBase).workers.length; 115 0 : let bpop = gameState.ai.HQ.getBaseByID(bBase).workers.length; 116 0 : if (apop > bpop) 117 0 : aa++; 118 0 : else if (bpop > apop) 119 0 : bb++; 120 : } 121 0 : return aa - bb; 122 : }); 123 : } 124 : 125 0 : if (this.metadata && this.metadata.base !== undefined && this.metadata.base === 0) 126 0 : this.metadata.base = this.trainers[0].getMetadata(PlayerID, "base"); 127 0 : this.trainers[0].train(gameState.getPlayerCiv(), this.type, this.number, this.metadata); 128 : 129 0 : this.onStart(gameState); 130 : }; 131 : 132 0 : PETRA.TrainingPlan.prototype.addItem = function(amount = 1) 133 : { 134 0 : this.number += amount; 135 : }; 136 : 137 0 : PETRA.TrainingPlan.prototype.Serialize = function() 138 : { 139 0 : return { 140 : "category": this.category, 141 : "type": this.type, 142 : "ID": this.ID, 143 : "metadata": this.metadata, 144 : "cost": this.cost.Serialize(), 145 : "number": this.number, 146 : "maxMerge": this.maxMerge 147 : }; 148 : }; 149 : 150 0 : PETRA.TrainingPlan.prototype.Deserialize = function(gameState, data) 151 : { 152 0 : for (let key in data) 153 0 : this[key] = data[key]; 154 : 155 0 : this.cost = new API3.Resources(); 156 0 : this.cost.Deserialize(data.cost); 157 : };