GunChleoc
Joined:
2013-10-07, 15:56 UTC+2.0
Posts: 3317
One Elder of Players
Location: RenderedRect
|
Posted at:
2016-02-04, 15:30 UTC+1.0
Looks like I need to run the script myself so I can debug. Do you still have your original script? It might be easier for me to debug from there.
Busy indexing nil values
Top
Quote
|
|
|
GunChleoc
Joined:
2013-10-07, 15:56 UTC+2.0
Posts: 3317
One Elder of Players
Location: RenderedRect
|
Posted at:
2016-02-04, 15:33 UTC+1.0
PkK wrote:
GunChleoc wrote:
The problem here is that the headquarters have different names now, depending on the tribe. So, you need to get the wl.map.TribeDescription for the player, then call get tribe.headquarters to get the building name.
https://wl.widelands.org/docs/wl/autogen_wl_map/#module-interfaces
Something like this should work:
~~~~
local hq_name = wl.Game().players[player.number].tribe.headquarters
local hq = wl.Game().players[player.number].get_buildings(hq_name)
~~~~
Would this work with the if test even when the player has been defeated? Would it crash or return 0, NULL or whatever it is in Lua for hq?
Philipp
Good point, one should check if the player is there before doing anything. Same goes for the building I guess.
Busy indexing nil values
Top
Quote
|
|
|
PkK
Topic Opener
Joined:
2012-01-06, 12:19 UTC+1.0
Posts: 236
Widelands-Forum-Junkie
|
Posted at:
2016-02-04, 15:38 UTC+1.0
GunChleoc wrote:
Looks like I need to run the script myself so I can debug. Do you still have your original script? It might be easier for me to debug from there.
The original (i.e. build 18) version can be found at:
http://pholia.tdi.informatik.uni-frankfurt.de/~philipp/widelands/barbarians/
My current version is
include "scripting/infrastructure.lua"
set_textdomain("tribes")
init = {
descname = _ "Headquarters cheat",
func = function(player, shared_in_start)
local sf = wl.Game().map.player_slots[player.number].starting_field
if shared_in_start then
sf = shared_in_start
else
player:allow_workers("all")
end
hq = prefilled_buildings(player, { "barbarians_headquarters", sf.x, sf.y,
wares = {
ax = 5,
bread_paddle = 2,
blackwood = 32,
cloth = 5,
coal = 12,
felling_ax = 4,
fire_tongs = 2,
fish = 6,
fishing_rod = 2,
gold = 4,
grout = 12,
hammer = 12,
hunting_spear = 2,
iron = 12,
iron_ore = 5,
kitchen_tools = 4,
meal = 4,
meat = 6,
pick = 8,
barbarians_bread = 8,
ration = 12,
granite = 40,
scythe = 6,
shovel = 4,
snack = 3,
thatch_reed = 24,
log = 80,
},
workers = {
barbarians_blacksmith = 2,
barbarians_brewer = 1,
barbarians_builder = 10,
barbarians_charcoal_burner = 1,
barbarians_carrier = 40,
barbarians_gardener = 1,
barbarians_geologist = 4,
barbarians_lime_burner = 1,
barbarians_lumberjack = 3,
barbarians_miner = 4,
barbarians_ranger = 1,
barbarians_stonemason = 2,
barbarians_ox = 5,
},
soldiers = {
[{0,0,0,0}] = 45,
}
})
place_building_in_region(player, "barbarians_battlearena", sf:region(12), {
wares = {
barbarians_bread = 8,
fish = 6,
meat = 6,
}
})
for i=1,100000 do
--sleep(600000)
sleep(1000)
--local hq = wl.Game().players[player.number].get_buildings("headquarters")
local hq = wl.Game().map:get_field(sf.x, sf.y).immovable
--local hq_name = wl.Game().players[player.number].tribe.headquarters
--local hq = wl.Game().players[player.number].get_buildings(hq_name)
if hq and hq.type == "warehouse" then
if hq:get_wares("water") < 1280 then
hq:set_wares("water", hq:get_wares("water") + 128)
end
if hq:get_wares("log") < 1280 then
hq:set_wares("log", hq:get_wares("log") + 128)
end
if hq:get_wares("granite") < 640 then
hq:set_wares("granite", hq:get_wares("granite") + 64)
end
if hq:get_wares("coal") < 240 then
hq:set_wares("coal", hq:get_wares("coal") + 24)
end
if hq:get_wares("ironore") < 80 then
hq:set_wares("ironore", hq:get_wares("ironore") + 8)
end
if hq:get_wares("fish") < 100 then
hq:set_wares("fish", hq:get_wares("fish") + 4)
end
if hq:get_wares("gold") < 100 then
hq:set_wares("gold", hq:get_wares("gold") + 4)
end
end
end
end
}
return init
I have similar ones for the other tribes.
Philipp
P.S.: I tend to use them on 8-player maps for (4 - #humans) of the AI players, so I get a total of 4 strong players. AIs with custom start script and each human player defeats one AI player before meeting another strong player.
Top
Quote
|
|
|
PkK
Topic Opener
Joined:
2012-01-06, 12:19 UTC+1.0
Posts: 236
Widelands-Forum-Junkie
|
Posted at:
2016-02-04, 15:40 UTC+1.0
GunChleoc wrote:
PkK wrote:
GunChleoc wrote:
The problem here is that the headquarters have different names now, depending on the tribe. So, you need to get the wl.map.TribeDescription for the player, then call get tribe.headquarters to get the building name.
https://wl.widelands.org/docs/wl/autogen_wl_map/#module-interfaces
Something like this should work:
~~~~
local hq_name = wl.Game().players[player.number].tribe.headquarters
local hq = wl.Game().players[player.number].get_buildings(hq_name)
~~~~
Would this work with the if test even when the player has been defeated? Would it crash or return 0, NULL or whatever it is in Lua for hq?
Philipp
Good point, one should check if the player is there before doing anything. Same goes for the building I guess.
The line
if hq and hq.type == "warehouse" then
was sufficient in the original script to keep the game from crashing after a player was defeated.
Philipp
Top
Quote
|
|
|
GunChleoc
Joined:
2013-10-07, 15:56 UTC+2.0
Posts: 3317
One Elder of Players
Location: RenderedRect
|
Posted at:
2016-02-04, 16:27 UTC+1.0
OK, here's my solution:
include "scripting/infrastructure.lua"
include "scripting/coroutine.lua"
set_textdomain("tribes")
function autofill_headquarters(player)
for i=1,100000 do
sleep(600)
local hq = wl.Game().players[player.number]:get_buildings("barbarians_headquarters")[1]
print(hq.descr.name);
if hq and hq.type == "warehouse" then
print("Headquarters" .. hq.name)
if hq:get_wares("water") < 1280 then
print("water!")
hq:set_wares("water", hq:get_wares("water") + 128)
end
if hq:get_wares("log") < 1280 then
hq:set_wares("log", hq:get_wares("log") + 128)
end
if hq:get_wares("granite") < 640 then
hq:set_wares("granite", hq:get_wares("granite") + 64)
end
if hq:get_wares("coal") < 240 then
hq:set_wares("coal", hq:get_wares("coal") + 24)
end
if hq:get_wares("iron_ore") < 80 then
hq:set_wares("iron_ore", hq:get_wares("iron_ore") + 8)
end
if hq:get_wares("fish") < 100 then
hq:set_wares("fish", hq:get_wares("fish") + 4)
end
if hq:get_wares("gold") < 100 then
hq:set_wares("gold", hq:get_wares("gold") + 4)
end
end
end
end
init = {
descname = _ "Headquarters cheat",
func = function(player, shared_in_start)
local sf = wl.Game().map.player_slots[player.number].starting_field
if shared_in_start then
sf = shared_in_start
else
player:allow_workers("all")
end
hq = prefilled_buildings(player, { "barbarians_headquarters", sf.x, sf.y,
wares = {
ax = 5,
bread_paddle = 2,
blackwood = 32,
cloth = 5,
coal = 12,
felling_ax = 4,
fire_tongs = 2,
fish = 6,
fishing_rod = 2,
gold = 4,
grout = 12,
hammer = 12,
hunting_spear = 2,
iron = 12,
iron_ore = 5,
kitchen_tools = 4,
meal = 4,
meat = 6,
pick = 8,
barbarians_bread = 8,
ration = 12,
granite = 40,
scythe = 6,
shovel = 4,
snack = 3,
thatch_reed = 24,
log = 80,
},
workers = {
barbarians_blacksmith = 2,
barbarians_brewer = 1,
barbarians_builder = 10,
barbarians_charcoal_burner = 1,
barbarians_carrier = 40,
barbarians_gardener = 1,
barbarians_geologist = 4,
barbarians_lime_burner = 1,
barbarians_lumberjack = 3,
barbarians_miner = 4,
barbarians_ranger = 1,
barbarians_stonemason = 2,
barbarians_ox = 5,
},
soldiers = {
[{0,0,0,0}] = 45,
}
})
place_building_in_region(player, "barbarians_battlearena", sf:region(12), {
wares = {
barbarians_bread = 8,
fish = 6,
meat = 6,
}
})
run(autofill_headquarters(player))
end
}
return init
This will print
barbarians_headquarters
barbarians_headquarters
barbarians_headquarters
barbarians_headquarters
barbarians_headquarters
This will access the building at least - you will still need to adjust the sleeptime, and I am not sure if the extra function is needed. You might need to compare hq.descr.type instead of hq.type - since we're getting an explicit building here, you could also cpmpare hq.descr.name == "barbarians_headquarters" instead.
Busy indexing nil values
Top
Quote
|
|
|
PkK
Topic Opener
Joined:
2012-01-06, 12:19 UTC+1.0
Posts: 236
Widelands-Forum-Junkie
|
Posted at:
2016-02-04, 17:03 UTC+1.0
Thanks a lot. Based on your version, I wrote this, which now mostly works:
include "scripting/infrastructure.lua"
include "scripting/coroutine.lua"
set_textdomain("tribes")
init = {
descname = _ "Headquarters cheat",
func = function(player, shared_in_start)
local sf = wl.Game().map.player_slots[player.number].starting_field
if shared_in_start then
sf = shared_in_start
else
player:allow_workers("all")
end
hq = prefilled_buildings(player, { "barbarians_headquarters", sf.x, sf.y,
wares = {
ax = 5,
bread_paddle = 2,
blackwood = 32,
cloth = 5,
coal = 12,
felling_ax = 4,
fire_tongs = 2,
fish = 6,
fishing_rod = 2,
gold = 4,
grout = 12,
hammer = 12,
hunting_spear = 2,
iron = 12,
iron_ore = 5,
kitchen_tools = 4,
meal = 4,
meat = 6,
pick = 8,
barbarians_bread = 8,
ration = 12,
granite = 40,
scythe = 6,
shovel = 4,
snack = 3,
thatch_reed = 24,
log = 80,
},
workers = {
barbarians_blacksmith = 2,
barbarians_brewer = 1,
barbarians_builder = 10,
barbarians_charcoal_burner = 1,
barbarians_carrier = 40,
barbarians_gardener = 1,
barbarians_geologist = 4,
barbarians_lime_burner = 1,
barbarians_lumberjack = 3,
barbarians_miner = 4,
barbarians_ranger = 1,
barbarians_stonemason = 2,
barbarians_ox = 5,
},
soldiers = {
[{0,0,0,0}] = 45,
}
})
place_building_in_region(player, "barbarians_battlearena", sf:region(12), {
wares = {
barbarians_bread = 8,
fish = 6,
meat = 6,
}
})
for i=1,100000 do
--sleep(600000)
sleep(5000)
local hq = wl.Game().players[player.number]:get_buildings("barbarians_headquarters")[1]
if hq and hq.descr.name == "barbarians_headquarters" then
if hq:get_wares("water") < 512 then
hq:set_wares("water", hq:get_wares("water") + 128)
end
if hq:get_wares("log") < 512 then
hq:set_wares("log", hq:get_wares("log") + 128)
end
if hq:get_wares("granite") < 512 then
hq:set_wares("granite", hq:get_wares("granite") + 64)
end
if hq:get_wares("coal") < 256 then
hq:set_wares("coal", hq:get_wares("coal") + 24)
end
if hq:get_wares("iron_ore") < 96 then
hq:set_wares("iron_ore", hq:get_wares("iron_ore") + 8)
end
if hq:get_wares("fish") < 64 then
hq:set_wares("fish", hq:get_wares("fish") + 4)
end
if hq:get_wares("gold") < 64 then
hq:set_wares("gold", hq:get_wares("gold") + 4)
end
end
end
end
}
return init
For most wares, it works. But for others it doesn't: E.g. now the amount of water keeps changing between 128 and 0 (I used a LAN game with me as observer to test). Do ware amounts now overflow at 256? AFAIR one could have a lot more in the past.
Philipp
Top
Quote
|
|
|
GunChleoc
Joined:
2013-10-07, 15:56 UTC+2.0
Posts: 3317
One Elder of Players
Location: RenderedRect
|
Posted at:
2016-02-04, 17:44 UTC+1.0
PkK wrote:
For most wares, it works. But for others it doesn't: E.g. now the amount of water keeps changing between 128 and 0 (I used a LAN game with me as observer to test). Do ware amounts now overflow at 256? AFAIR one could have a lot more in the past.
I just checked - looks like they do, which is not good. I will change the datatype from 8 to 32 bit.
ETA: Merge request is up: https://code.launchpad.net/~widelands-dev/widelands/fix_ware_amount/+merge/285099
Thanks for flagging this up
ETA: Merged at revision 7788.
Edited:
2016-02-05, 15:20 UTC+1.0
Busy indexing nil values
Top
Quote
|