building-hacks: added lua convenience function, made impassible tile fix optional.

develop
Warmist 2014-01-07 18:14:54 +02:00
parent b1e7356e63
commit 834350012f
2 changed files with 145 additions and 26 deletions

@ -37,6 +37,7 @@ struct graphic_tile //could do just 31x31 and be done, but it's nicer to have fl
struct workshop_hack_data struct workshop_hack_data
{ {
int32_t myType; int32_t myType;
bool impassible_fix;
//machine stuff //machine stuff
df::machine_tile_set connections; df::machine_tile_set connections;
df::power_info powerInfo; df::power_info powerInfo;
@ -76,8 +77,11 @@ struct work_hook : df::building_workshopst{
} }
DEFINE_VMETHOD_INTERPOSE(uint32_t,getImpassableOccupancy,()) DEFINE_VMETHOD_INTERPOSE(uint32_t,getImpassableOccupancy,())
{ {
if(find_def()) if(auto def = find_def())
{
if(def->impassible_fix)
return tile_building_occ::Impassable; return tile_building_occ::Impassable;
}
return INTERPOSE_NEXT(getImpassableOccupancy)(); return INTERPOSE_NEXT(getImpassableOccupancy)();
} }
@ -213,7 +217,7 @@ struct work_hook : df::building_workshopst{
} }
} }
} }
int w=db->x2-db->x1; int w=db->x2-db->x1+1;
std::vector<graphic_tile> &cur_frame=def->frames[frame]; std::vector<graphic_tile> &cur_frame=def->frames[frame];
for(int i=0;i<cur_frame.size();i++) for(int i=0;i<cur_frame.size();i++)
{ {
@ -258,6 +262,13 @@ static void loadFrames(lua_State* L,workshop_hack_data& def,int stack_pos)
graphic_tile t; graphic_tile t;
lua_pushnumber(L,1); lua_pushnumber(L,1);
lua_gettable(L,-2); lua_gettable(L,-2);
if(lua_isnil(L,-1))
{
t.tile=-1;
lua_pop(L,1);
}
else
{
t.tile=lua_tonumber(L,-1); t.tile=lua_tonumber(L,-1);
lua_pop(L,1); lua_pop(L,1);
@ -276,6 +287,7 @@ static void loadFrames(lua_State* L,workshop_hack_data& def,int stack_pos)
t.bright=lua_tonumber(L,-1); t.bright=lua_tonumber(L,-1);
lua_pop(L,1); lua_pop(L,1);
}
frame.push_back(t); frame.push_back(t);
lua_pop(L,1); lua_pop(L,1);
} }
@ -285,17 +297,18 @@ static void loadFrames(lua_State* L,workshop_hack_data& def,int stack_pos)
lua_pop(L,1); lua_pop(L,1);
return ; return ;
} }
//arguments: custom type, consumed power, produced power, list of connection points, update skip(0/nil to disable) //arguments: 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) // table of frames,frame to tick ratio (-1 for machine control)
static int addBuilding(lua_State* L) static int addBuilding(lua_State* L)
{ {
workshop_hack_data newDefinition; workshop_hack_data newDefinition;
newDefinition.myType=luaL_checkint(L,1); newDefinition.myType=luaL_checkint(L,1);
newDefinition.powerInfo.consumed=luaL_checkint(L,2); newDefinition.impassible_fix=luaL_checkint(L,2);
newDefinition.powerInfo.produced=luaL_checkint(L,3); newDefinition.powerInfo.consumed=luaL_checkint(L,3);
newDefinition.powerInfo.produced=luaL_checkint(L,4);
//table of machine connection points //table of machine connection points
luaL_checktype(L,4,LUA_TTABLE); luaL_checktype(L,5,LUA_TTABLE);
lua_pushvalue(L,4); lua_pushvalue(L,5);
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");
@ -312,12 +325,12 @@ static int addBuilding(lua_State* L)
} }
lua_pop(L,1); lua_pop(L,1);
//updates //updates
newDefinition.skip_updates=luaL_optinteger(L,5,0); newDefinition.skip_updates=luaL_optinteger(L,6,0);
//animation //animation
if(!lua_isnil(L,6) && lua_gettop(L)>5) if(!lua_isnil(L,7))
{ {
loadFrames(L,newDefinition,6); loadFrames(L,newDefinition,7);
newDefinition.frame_skip=luaL_optinteger(L,7,-1); newDefinition.frame_skip=luaL_optinteger(L,8,-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)

@ -1,3 +1,109 @@
local _ENV = mkmodule('plugins.building-hacks') local _ENV = mkmodule('plugins.building-hacks')
--[[
from native:
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))
from here:
registerBuilding{
name -- custom workshop id e.g. SOAPMAKER << required!
fix_impassible -- make impassible tiles impassible to liquids too
consume -- how much machine power is needed to work
produce -- how much machine power is produced
gears -- a table or {x=?,y=?} of connection points for machines
action -- a table of number (how much ticks to skip) and a function which gets called on shop update
animate -- a table of
frames -- a table of
tables of 4 numbers (tile,fore,back,bright) OR
empty table (tile not modified) OR
{x=<number> y=<number> + 4 numbers like in first case} -- this generates full frame even, usefull for animations that change little (1-2 tiles)
frameLenght -- how many ticks does one frame take OR
isMechanical -- a bool that says to try to match to mechanical system (i.e. how gears are turning)
}
]]
_registeredStuff={}
local function unregall(state)
if state==SC_WORLD_UNLOADED then
onUpdateAction._library=nil
dfhack.onStateChange.building_hacks= nil
_registeredStuff={}
end
end
local function onUpdateLocal(workshop)
local f=_registeredStuff[workshop:getCustomType()]
if f then
f(workshop)
end
end
local function findCustomWorkshop(name)
local raws=df.global.world.raws.buildings.all
for k,v in ipairs(raws) do
if v.code==name then
return v
end
end
end
local function registerUpdateAction(shopId,callback)
_registeredStuff[shopId]=callback
onUpdateAction._library=onUpdateLocal
dfhack.onStateChange.building_hacks=unregall
end
local function generateFrame(tiles,w,h)
local mTiles={}
for k,v in ipairs(tiles) do
mTiles[v.x]=mTiles[v.x] or {}
mTiles[v.x][v.y]=v
end
local ret={}
for ty=0,h-1 do
for tx=0,w-1 do
if mTiles[tx] and mTiles[tx][ty] then
table.insert(ret,mTiles[tx][ty]) -- leaves x and y in but who cares
else
table.insert(ret,{})
end
end
end
return ret
end
local function processFrames(shop_def,frames)
local w,h=shop_def.dim_x,shop_def.dim_y
for frame_id,frame in ipairs(frames) do
if frame[1].x~=nil then
frames[frame_id]=generateFrame(frame,w,h)
end
end
return frames
end
function registerBuilding(args)
local shop_def=findCustomWorkshop(args.name)
local shop_id=shop_def.id
local fix_impassible
if args.fix_impassible then
fix_impassible=1
else
fix_impassible=0
end
local consume=args.consume or 0
local produce=args.produce or 0
local gears=args.gears or {}
local action=args.action --could be nil
local updateSkip=0
if action~=nil then
updateSkip=action[1]
registerUpdateAction(shop_id,action[2])
end
local animate=args.animate
local frameLength=1
local frames
if animate~=nil then
frameLength=animate.frameLength
if animate.isMechanical then
frameLength=-1
end
frames=processFrames(shop_def,animate.frames)
end
addBuilding(shop_id,fix_impassible,consume,produce,gears,updateSkip,frames,frameLength)
end
return _ENV return _ENV