Building hacks changes.

Fixed buildings not consuming correct value of power. Added way to ignore unpowered state. Added setPower/getPower to change how much power building uses on the fly.
develop
Warmist 2015-02-24 15:37:38 +02:00
parent f81bee7a94
commit e9ab892369
4 changed files with 123 additions and 23 deletions

@ -3329,21 +3329,26 @@ Functions
``registerBuilding(table)`` where table must contain name, as a workshop raw name, the rest are optional: ``registerBuilding(table)`` where table must contain name, as a workshop raw name, the rest are optional:
1. name -- custom workshop id e.g. ``SOAPMAKER`` 1. name -- custom workshop id e.g. ``SOAPMAKER``
2. fix_impassible -- if true make impassible tiles impassible to liquids too 2. fix_impassible -- if true make impassible tiles impassible to liquids too
3. consume -- how much machine power is needed to work. Disables reactions if not supplied enough 3. consume -- how much machine power is needed to work. Disables reactions if not supplied enough and needs_power=1
4. produce -- how much machine power is produced. Use discouraged as there is no way to change this at runtime 4. produce -- how much machine power is produced.
5. gears -- a table or ``{x=?,y=?}`` of connection points for machines 5. needs_power -- if produced in network < consumed stop working, default true
6. action -- a table of number (how much ticks to skip) and a function which gets called on shop update 6. gears -- a table or ``{x=?,y=?}`` of connection points for machines
7. animate -- a table of frames which can be a table of: 7. action -- a table of number (how much ticks to skip) and a function which gets called on shop update
8. animate -- a table of frames which can be a table of:
a. tables of 4 numbers ``{tile,fore,back,bright}`` OR a. tables of 4 numbers ``{tile,fore,back,bright}`` OR
b. empty table (tile not modified) OR b. empty table (tile not modified) OR
c. ``{x=<number> y=<number> + 4 numbers like in first case}``, this generates full frame useful for animations that change little (1-2 tiles) c. ``{x=<number> y=<number> + 4 numbers like in first case}``, this generates full frame useful for animations that change little (1-2 tiles)
8. canBeRoomSubset -- a flag if this building can be counted in room. 1 means it can, 0 means it can't and -1 default building behaviour 9. canBeRoomSubset -- a flag if this building can be counted in room. 1 means it can, 0 means it can't and -1 default building behaviour
Animate table also might contain: Animate table also might contain:
1. frameLenght -- how many ticks does one frame take OR 1. frameLenght -- how many ticks does one frame take OR
2. isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning) 2. isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
``getPower(building)`` returns two number - produced and consumed power if building can be modified and returns nothing otherwise
``setPower(building,produced,consumed)`` sets current productiona and consumption for a building.
Examples Examples
-------- --------

@ -10,6 +10,7 @@ DFHack Future
Fixes Fixes
Made PRELOAD_LIB more extensible on Linux Made PRELOAD_LIB more extensible on Linux
add-spatter/eventful: Fixed crash on world load add-spatter/eventful: Fixed crash on world load
building-hacks: made buildings produce/consume correct amount of power
Gave add-thought a proper subthought arg. Gave add-thought a proper subthought arg.
fix-armory compiles and is available again (albeit with issues) fix-armory compiles and is available again (albeit with issues)
gui/gm-editor: Added search option (accessible with "s") gui/gm-editor: Added search option (accessible with "s")
@ -24,6 +25,7 @@ DFHack Future
tradereq-pet-gender: Displays pet genders on the trade request screen tradereq-pet-gender: Displays pet genders on the trade request screen
Removed Removed
Misc Improvements Misc Improvements
building-hacks: Added a way to allow building to work even if it consumes more power than is available. Added setPower/getPower functions.
catsplosion: Can now trigger pregnancies in (most) other creatures catsplosion: Can now trigger pregnancies in (most) other creatures
exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities exportlegends: 'info' and 'all' exports legends_plus xml with more data for legends utilities
remotefortressreader: Exposes more information remotefortressreader: Exposes more information

@ -19,6 +19,8 @@
#include "df/coord.h" #include "df/coord.h"
#include "df/tile_building_occ.h" #include "df/tile_building_occ.h"
#include "df/building_drawbuffer.h" #include "df/building_drawbuffer.h"
#include "df/general_ref_creaturest.h" // needed for power information storage
#include "modules/Buildings.h"
#include <map> #include <map>
@ -42,6 +44,7 @@ struct workshop_hack_data
//machine stuff //machine stuff
df::machine_tile_set connections; df::machine_tile_set connections;
df::power_info powerInfo; df::power_info powerInfo;
bool needs_power;
//animation //animation
std::vector<std::vector<graphic_tile> > frames; std::vector<std::vector<graphic_tile> > frames;
bool machine_timing; //6 frames used in vanilla bool machine_timing; //6 frames used in vanilla
@ -60,6 +63,7 @@ DFHACK_PLUGIN_LUA_EVENTS {
DFHACK_LUA_EVENT(onUpdateAction), DFHACK_LUA_EVENT(onUpdateAction),
DFHACK_LUA_END DFHACK_LUA_END
}; };
struct work_hook : df::building_workshopst{ struct work_hook : df::building_workshopst{
typedef df::building_workshopst interpose_base; typedef df::building_workshopst interpose_base;
@ -77,6 +81,54 @@ struct work_hook : df::building_workshopst{
{ {
return getBuildStage() >= getMaxBuildStage(); return getBuildStage() >= getMaxBuildStage();
} }
bool get_current_power(df::power_info* info)
{
if (workshop_hack_data* def = find_def())
{
df::general_ref_creaturest* ref = static_cast<df::general_ref_creaturest*>(DFHack::Buildings::getGeneralRef(this, general_ref_type::CREATURE));
if (ref)
{
info->produced = ref->anon_1;
info->consumed = ref->anon_2;
return true;
}
else
{
info->produced = def->powerInfo.produced;
info->consumed = def->powerInfo.consumed;
return true;
}
//try getting ref, if not return from def
}
return false;
}
void set_current_power(int produced, int consumed)
{
if(machine.machine_id != -1) //if connected to machine, update the machine network production
{
df::machine* target_machine = df::machine::find(machine.machine_id);
if (target_machine)
{
df::power_info old_power;
get_current_power(&old_power);
target_machine->min_power += consumed - old_power.consumed;
target_machine->cur_power += produced - old_power.produced;
}
}
df::general_ref_creaturest* ref = static_cast<df::general_ref_creaturest*>(DFHack::Buildings::getGeneralRef(this, general_ref_type::CREATURE));
if (ref)
{
ref->anon_1 = produced;
ref->anon_2 = consumed;
}
else
{
ref = df::allocate<df::general_ref_creaturest>();
ref->anon_1 = produced;
ref->anon_2 = consumed;
general_refs.push_back(ref);
}
}
DEFINE_VMETHOD_INTERPOSE(uint32_t,getImpassableOccupancy,()) DEFINE_VMETHOD_INTERPOSE(uint32_t,getImpassableOccupancy,())
{ {
if(auto def = find_def()) if(auto def = find_def())
@ -89,13 +141,12 @@ struct work_hook : df::building_workshopst{
DEFINE_VMETHOD_INTERPOSE(void, getPowerInfo, (df::power_info *info)) DEFINE_VMETHOD_INTERPOSE(void, getPowerInfo, (df::power_info *info))
{ {
if (auto def = find_def()) if (auto def = find_def())
{ {
info->produced = def->powerInfo.produced; df::power_info power;
info->consumed = def->powerInfo.consumed; get_current_power(info);
return; return;
} }
INTERPOSE_NEXT(getPowerInfo)(info); INTERPOSE_NEXT(getPowerInfo)(info);
} }
DEFINE_VMETHOD_INTERPOSE(df::machine_info*, getMachineInfo, ()) DEFINE_VMETHOD_INTERPOSE(df::machine_info*, getMachineInfo, ())
@ -108,7 +159,9 @@ struct work_hook : df::building_workshopst{
DEFINE_VMETHOD_INTERPOSE(bool, isPowerSource, ()) DEFINE_VMETHOD_INTERPOSE(bool, isPowerSource, ())
{ {
workshop_hack_data* def=find_def(); workshop_hack_data* def=find_def();
if (def && def->powerInfo.produced>0) df::power_info power;
get_current_power(&power);
if (def && power.produced>0)
return true; return true;
return INTERPOSE_NEXT(isPowerSource)(); return INTERPOSE_NEXT(isPowerSource)();
@ -164,7 +217,11 @@ struct work_hook : df::building_workshopst{
{ {
if (auto def = find_def()) if (auto def = find_def())
{ {
if(def->powerInfo.consumed==0) if (!def->needs_power)
return false;
df::power_info power;
get_current_power(&power);
if (power.consumed == 0)
return false; return false;
if(machine.machine_id==-1) if(machine.machine_id==-1)
return true; return true;
@ -257,6 +314,9 @@ IMPLEMENT_VMETHOD_INTERPOSE(work_hook, isUnpowered);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, canBeRoomSubset); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, canBeRoomSubset);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, updateAction); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, updateAction);
IMPLEMENT_VMETHOD_INTERPOSE(work_hook, drawBuilding); IMPLEMENT_VMETHOD_INTERPOSE(work_hook, drawBuilding);
void clear_mapping() void clear_mapping()
{ {
hacked_workshops.clear(); hacked_workshops.clear();
@ -318,9 +378,10 @@ static int addBuilding(lua_State* L)
newDefinition.impassible_fix=luaL_checkint(L,2); newDefinition.impassible_fix=luaL_checkint(L,2);
newDefinition.powerInfo.consumed=luaL_checkint(L,3); newDefinition.powerInfo.consumed=luaL_checkint(L,3);
newDefinition.powerInfo.produced=luaL_checkint(L,4); newDefinition.powerInfo.produced=luaL_checkint(L,4);
newDefinition.needs_power = luaL_optinteger(L, 5, 1);
//table of machine connection points //table of machine connection points
luaL_checktype(L,5,LUA_TTABLE); luaL_checktype(L,6,LUA_TTABLE);
lua_pushvalue(L,5); lua_pushvalue(L,6);
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, -2) != 0) { while (lua_next(L, -2) != 0) {
lua_getfield(L,-1,"x"); lua_getfield(L,-1,"x");
@ -337,12 +398,12 @@ static int addBuilding(lua_State* L)
} }
lua_pop(L,1); lua_pop(L,1);
//updates //updates
newDefinition.skip_updates=luaL_optinteger(L,6,0); newDefinition.skip_updates=luaL_optinteger(L,7,0);
//animation //animation
if(!lua_isnil(L,7)) if(!lua_isnil(L,8))
{ {
loadFrames(L,newDefinition,7); loadFrames(L,newDefinition,8);
newDefinition.frame_skip=luaL_optinteger(L,8,-1); newDefinition.frame_skip=luaL_optinteger(L,9,-1);
if(newDefinition.frame_skip==0) if(newDefinition.frame_skip==0)
newDefinition.frame_skip=1; newDefinition.frame_skip=1;
if(newDefinition.frame_skip<0) if(newDefinition.frame_skip<0)
@ -350,12 +411,41 @@ static int addBuilding(lua_State* L)
else else
newDefinition.machine_timing=false; newDefinition.machine_timing=false;
} }
newDefinition.room_subset=luaL_optinteger(L,9,-1); newDefinition.room_subset=luaL_optinteger(L,10,-1);
hacked_workshops[newDefinition.myType]=newDefinition; hacked_workshops[newDefinition.myType]=newDefinition;
return 0; return 0;
} }
static void setPower(df::building_workshopst* workshop, int power_produced, int power_consumed)
{
work_hook* ptr = static_cast<work_hook*>(workshop);
if (workshop_hack_data* def = ptr->find_def())//check if it's really hacked workshop
{
ptr->set_current_power(power_produced, power_consumed);
}
}
static int getPower(lua_State*L)
{
auto workshop = Lua::CheckDFObject<df::building_workshopst>(L, 1);
work_hook* ptr = static_cast<work_hook*>(workshop);
if (!ptr)
return 0;
if (workshop_hack_data* def = ptr->find_def())//check if it's really hacked workshop
{
df::power_info info;
ptr->get_current_power(&info);
lua_pushinteger(L, info.produced);
lua_pushinteger(L, info.consumed);
return 2;
}
return 0;
}
DFHACK_PLUGIN_LUA_FUNCTIONS{
DFHACK_LUA_FUNCTION(setPower),
DFHACK_LUA_END
};
DFHACK_PLUGIN_LUA_COMMANDS{ DFHACK_PLUGIN_LUA_COMMANDS{
DFHACK_LUA_COMMAND(addBuilding), DFHACK_LUA_COMMAND(addBuilding),
DFHACK_LUA_COMMAND(getPower),
DFHACK_LUA_END DFHACK_LUA_END
}; };
static void enable_hooks(bool enable) static void enable_hooks(bool enable)

@ -3,6 +3,8 @@ local _ENV = mkmodule('plugins.building-hacks')
from native: from native:
addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points, addBuilding(custom type,impassible fix (bool), consumed power, produced power, list of connection points,
update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control)) update skip(0/nil to disable),table of frames,frame to tick ratio (-1 for machine control))
getPower(bld) -- 2 or 0 returns, produced and consumed
setPower(bld,produced, consumed)
from here: from here:
registerBuilding{ registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required! name -- custom workshop id e.g. SOAPMAKER << required!
@ -85,6 +87,7 @@ function registerBuilding(args)
end end
local consume=args.consume or 0 local consume=args.consume or 0
local produce=args.produce or 0 local produce=args.produce or 0
local needs_power=args.needs_power or 1
local gears=args.gears or {} local gears=args.gears or {}
local action=args.action --could be nil local action=args.action --could be nil
local updateSkip=0 local updateSkip=0
@ -103,7 +106,7 @@ function registerBuilding(args)
frames=processFrames(shop_def,animate.frames) frames=processFrames(shop_def,animate.frames)
end end
local roomSubset=args.canBeRoomSubset or -1 local roomSubset=args.canBeRoomSubset or -1
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength,roomSubset) addBuilding(shop_id,fix_impassible,consume,produce,needs_power,gears,updateSkip,frames,frameLength,roomSubset)
end end
return _ENV return _ENV