Line data Source code
1 : function Cheat(input)
2 : {
3 0 : if (input.player < 0)
4 0 : return;
5 :
6 0 : const cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
7 0 : const playerEnt = cmpPlayerManager.GetPlayerByID(input.player);
8 0 : if (playerEnt == INVALID_ENTITY)
9 0 : return;
10 0 : const cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player);
11 0 : if (!cmpPlayer?.GetCheatsEnabled())
12 0 : return;
13 :
14 0 : const cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
15 :
16 0 : switch(input.action)
17 : {
18 : case "addresource":
19 0 : if (isNaN(input.parameter))
20 0 : return;
21 0 : cmpPlayer.AddResource(input.text, input.parameter);
22 0 : return;
23 : case "revealmap":
24 0 : Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).SetLosRevealAll(-1, true);
25 0 : return;
26 : case "maxpopulation":
27 0 : cmpPlayer.SetPopulationBonuses((cmpPlayerManager.GetMaxWorldPopulation() || cmpPlayer.GetMaxPopulation()) + 500);
28 0 : return;
29 : case "changemaxpopulation":
30 : {
31 0 : Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager).AddModifiers("cheat/maxpopulation", {
32 : "Player/MaxPopulation": [{ "affects": ["Player"], "add": 500 }],
33 : }, playerEnt);
34 0 : return;
35 : }
36 : case "convertunit":
37 0 : if (isNaN(input.parameter))
38 0 : return;
39 0 : const playerID = (input.parameter > -1 && QueryPlayerIDInterface(input.parameter) || cmpPlayer).GetPlayerID();
40 0 : for (const ent of input.selected)
41 0 : Engine.QueryInterface(ent, IID_Ownership)?.SetOwner(playerID);
42 0 : return;
43 : case "killunits":
44 0 : for (const ent of input.selected)
45 : {
46 0 : const cmpHealth = Engine.QueryInterface(ent, IID_Health);
47 0 : if (cmpHealth)
48 0 : cmpHealth.Kill();
49 : else
50 0 : Engine.DestroyEntity(ent);
51 : }
52 0 : return;
53 : case "defeatplayer":
54 0 : if (isNaN(input.parameter))
55 0 : return;
56 0 : QueryPlayerIDInterface(input.parameter)?.Defeat(
57 : markForTranslation("%(player)s has been defeated (cheat).")
58 : );
59 0 : return;
60 : case "createunits":
61 : {
62 0 : if (isNaN(input.player) || isNaN(input.parameter))
63 0 : return;
64 :
65 0 : const cmpTrainer = input.selected.length && Engine.QueryInterface(input.selected[0], IID_Trainer);
66 0 : if (!cmpTrainer)
67 : {
68 0 : cmpGuiInterface.PushNotification({
69 : "type": "text",
70 : "players": [input.player],
71 : "message": markForTranslation("You need to select a building that trains units."),
72 : "translateMessage": true
73 : });
74 0 : return;
75 : }
76 :
77 0 : let owner = input.player;
78 0 : const cmpOwnership = Engine.QueryInterface(input.selected[0], IID_Ownership);
79 0 : if (cmpOwnership)
80 0 : owner = cmpOwnership.GetOwner();
81 0 : for (let i = 0; i < Math.min(input.parameter, cmpPlayer.GetMaxPopulation() - cmpPlayer.GetPopulationCount()); ++i)
82 : {
83 0 : const batch = new cmpTrainer.Item(input.templates[i % input.templates.length], 1, input.selected[0], null);
84 0 : batch.player = owner;
85 0 : batch.Finish();
86 0 : if (!batch.IsFinished())
87 0 : batch.Stop();
88 : }
89 0 : return;
90 : }
91 : case "fastactions":
92 : {
93 0 : const cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager);
94 0 : if (cmpModifiersManager.HasAnyModifier("cheat/fastactions", playerEnt))
95 0 : cmpModifiersManager.RemoveAllModifiers("cheat/fastactions", playerEnt);
96 : else
97 0 : cmpModifiersManager.AddModifiers("cheat/fastactions", {
98 : "Cost/BuildTime": [{ "affects": [["Structure"], ["Unit"]], "multiply": 0.01 }],
99 : "ResourceGatherer/BaseSpeed": [{ "affects": [["Structure"], ["Unit"]], "multiply": 1000 }],
100 : "Pack/Time": [{ "affects": [["Structure"], ["Unit"]], "multiply": 0.01 }],
101 : "Upgrade/Time": [{ "affects": [["Structure"], ["Unit"]], "multiply": 0.01 }],
102 : "Researcher/TechCostMultiplier/time": [{ "affects": [["Structure"], ["Unit"]], "multiply": 0.01 }]
103 : }, playerEnt);
104 0 : return;
105 : }
106 : case "changephase":
107 : {
108 0 : const cmpTechnologyManager = Engine.QueryInterface(playerEnt, IID_TechnologyManager);
109 0 : if (!cmpTechnologyManager)
110 0 : return;
111 :
112 : // store the phase we want in the next input parameter
113 : let parameter;
114 0 : if (!cmpTechnologyManager.IsTechnologyResearched("phase_town"))
115 0 : parameter = "phase_town";
116 0 : else if (!cmpTechnologyManager.IsTechnologyResearched("phase_city"))
117 0 : parameter = "phase_city";
118 : else
119 0 : return;
120 :
121 0 : const civ = Engine.QueryInterface(playerEnt, IID_Identity).GetCiv();
122 0 : parameter += TechnologyTemplates.Has(parameter + "_" + civ) ? "_" + civ : "_generic";
123 :
124 0 : Cheat({
125 : "player": input.player,
126 : "action": "researchTechnology",
127 : "parameter": parameter,
128 : "selected": input.selected
129 : });
130 0 : return;
131 : }
132 : case "researchTechnology":
133 : {
134 0 : if (!input.parameter.length)
135 0 : return;
136 :
137 0 : let techname = input.parameter;
138 0 : const cmpTechnologyManager = Engine.QueryInterface(playerEnt, IID_TechnologyManager);
139 0 : if (!cmpTechnologyManager)
140 0 : return;
141 :
142 : // check, if building is selected
143 0 : if (input.selected[0])
144 : {
145 0 : const cmpResearcher = Engine.QueryInterface(input.selected[0], IID_Researcher);
146 0 : if (cmpResearcher)
147 : {
148 : // try to spilt the input
149 0 : const tmp = input.parameter.split(/\s+/);
150 0 : const number = +tmp[0];
151 0 : const pair = tmp.length > 1 && (tmp[1] == "top" || tmp[1] == "bottom") ? tmp[1] : "top"; // use top as default value
152 :
153 : // check, if valid number was parsed.
154 0 : if (!isNaN(number))
155 : {
156 : // get name of tech
157 0 : const techs = cmpResearcher.GetTechnologiesList();
158 0 : if (number > 0 && number <= techs.length)
159 : {
160 0 : const tech = techs[number-1];
161 0 : if (!tech)
162 0 : return;
163 :
164 : // get name of tech
165 0 : if (tech.pair)
166 0 : techname = tech[pair];
167 : else
168 0 : techname = tech;
169 : }
170 : else
171 0 : return;
172 : }
173 : }
174 : }
175 :
176 0 : if (TechnologyTemplates.Has(techname))
177 0 : cmpTechnologyManager.ResearchTechnology(techname);
178 0 : return;
179 : }
180 : case "metaCheat":
181 0 : for (const resource of Resources.GetCodes())
182 0 : Cheat({ "player": input.player, "action": "addresource", "text": resource, "parameter": input.parameter });
183 0 : Cheat({ "player": input.player, "action": "maxpopulation" });
184 0 : Cheat({ "player": input.player, "action": "changemaxpopulation" });
185 0 : Cheat({ "player": input.player, "action": "fastactions" });
186 0 : for (let i = 0; i < 2; ++i)
187 0 : Cheat({ "player": input.player, "action": "changephase", "selected": input.selected });
188 0 : return;
189 : case "playRetro":
190 0 : const play = input.parameter.toLowerCase() != "off";
191 0 : cmpGuiInterface.PushNotification({
192 : "type": "play-tracks",
193 : "tracks": play && input.parameter.split(" "),
194 : "lock": play,
195 : "players": [input.player]
196 : });
197 0 : return;
198 :
199 : default:
200 0 : warn("Cheat '" + input.action + "' is not implemented");
201 0 : return;
202 : }
203 : }
204 :
205 0 : Engine.RegisterGlobal("Cheat", Cheat);
|