diff --git a/pkg/base/client_start.lua b/pkg/base/client_start.lua index ca04b37..675159c 100644 --- a/pkg/base/client_start.lua +++ b/pkg/base/client_start.lua @@ -392,6 +392,8 @@ mdl_test = client.model_load_pmf("pkg/base/pmf/test.pmf") mdl_test_bone = client.model_bone_find(mdl_test, "test") mdl_cube = client.model_load_pmf("pkg/base/pmf/cube.pmf") mdl_cube_bone = client.model_bone_find(mdl_cube, "bncube") +mdl_Xcube = client.model_load_pmf("pkg/base/pmf/Xcube.pmf") +mdl_Xcube_bone = client.model_bone_find(mdl_cube, "bnXcube") mdl_spade, mdl_spade_bone = client.model_load_pmf("pkg/base/pmf/spade.pmf"), 0 mdl_block, mdl_block_bone = client.model_load_pmf("pkg/base/pmf/block.pmf"), 0 weapon_models[WPN_RIFLE] = client.model_load_pmf("pkg/base/pmf/rifle.pmf") diff --git a/pkg/base/common.lua b/pkg/base/common.lua index 1067ab7..0ec931d 100644 --- a/pkg/base/common.lua +++ b/pkg/base/common.lua @@ -1,434 +1,435 @@ ---[[ - This file is part of Ice Lua Components. - - Ice Lua Components is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Ice Lua Components is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Ice Lua Components. If not, see . -]] - -print("base dir:",common.base_dir) - -dofile("pkg/base/version.lua") - --- base dir stuff -DIR_PKG_ROOT = DIR_PKG_ROOT or "pkg/base" -DIR_PKG_LIB = DIR_PKG_LIB or DIR_PKG_ROOT -DIR_PKG_PMF = DIR_PKG_PMF or DIR_PKG_ROOT.."/pmf" -DIR_PKG_GFX = DIR_PKG_GFX or DIR_PKG_ROOT.."/gfx" -DIR_PKG_WAV = DIR_PKG_WAV or DIR_PKG_ROOT.."/wav" -DIR_PKG_MAP = DIR_PKG_MAP or "pkg/maps" - -MAP_DEFAULT = MAP_DEFAULT or DIR_PKG_MAP.."/mesa.vxl" - -LIB_LIST = LIB_LIST or { - DIR_PKG_LIB.."/icegui/widgets.lua", - - DIR_PKG_LIB.."/lib_bits.lua", - DIR_PKG_LIB.."/lib_collect.lua", - DIR_PKG_LIB.."/lib_gui.lua", - DIR_PKG_LIB.."/lib_map.lua", - DIR_PKG_LIB.."/lib_namegen.lua", - DIR_PKG_LIB.."/lib_pmf.lua", - DIR_PKG_LIB.."/lib_sdlkey.lua", - DIR_PKG_LIB.."/lib_util.lua", - DIR_PKG_LIB.."/lib_vector.lua", - - DIR_PKG_LIB.."/obj_player.lua", - DIR_PKG_LIB.."/obj_intent.lua", - DIR_PKG_LIB.."/obj_nade.lua", -} - --- load libs -local i -for i=1,#LIB_LIST do - local asdf_qwerty = i - i = nil - dofile(LIB_LIST[asdf_qwerty]) - i = asdf_qwerty -end -i = nil - - --- mode stuff -MODE_DEBUG_SHOWBOXES = false -MODE_CHEAT_FLY = false - -MODE_AUTOCLIMB = true -MODE_AIRJUMP = false -MODE_SOFTCROUCH = true - -MODE_NADE_SPEED = 30.0 -MODE_NADE_STEP = 0.1 -MODE_NADE_FUSE = 3.0 -MODE_NADE_ADAMP = 0.5 -MODE_NADE_BDAMP = 1.0 -MODE_NADE_RANGE = 8.0 -MODE_NADE_DAMAGE = 500.0 - -MODE_MINIMAP_RCIRC = false -MODE_ENABLE_MINIMAP = true -MODE_MAP_TRACERS = false -- TODO! - -MODE_TILT_SLOWDOWN = false -- TODO! -MODE_TILT_DOWN_NOCLIMB = false -- TODO! - -MODE_DRUNKCAM_VELOCITY = false -- keep this off unless you want to throw up -MODE_DRUNKCAM_LOCALTURN = true -- this is the one you're looking for. -MODE_DRUNKCAM_CORRECTSPEED = 10.0 - -MODE_DELAY_SPADE_DIG = 1.0 -MODE_DELAY_SPADE_HIT = 0.25 -MODE_DELAY_BLOCK_BUILD = 0.5 -MODE_DELAY_TOOL_CHANGE = 0.2 -MODE_DELAY_NADE_THROW = 0.5 - -MODE_BLOCK_HEALTH = 100 -MODE_BLOCK_DAMAGE_SPADE = 34 -MODE_BLOCK_DAMAGE_RIFLE = 34 -MODE_BLOCK_REGEN_TIME = 15.0 - -MODE_RCIRC_LINGER = 60.0 -MODE_RESPAWN_TIME = 8.0 - -MODE_CHAT_LINGER = 15.0 -MODE_CHAT_MAX = 10 -MODE_CHAT_STRMAX = 102 - --- scoring -SCORE_INTEL = 10 -SCORE_KILL = 1 -SCORE_TEAMKILL = -1 -SCORE_SUICIDE = -1 - --- tools -TOOL_SPADE = 0 -TOOL_BLOCK = 1 -TOOL_GUN = 2 -TOOL_NADE = 3 - --- sounds -if client then - client.wav_cube_size(0.5) - wav_rifle_shot = common.wav_load(DIR_PKG_WAV.."/rifle-shot.wav") - wav_rifle_reload = common.wav_load(DIR_PKG_WAV.."/rifle-reload.wav") - wav_whoosh = common.wav_load(DIR_PKG_WAV.."/whoosh.wav") - wav_buld = common.wav_load(DIR_PKG_WAV.."/buld.wav") - wav_grif = common.wav_load(DIR_PKG_WAV.."/grif.wav") - wav_hammer = common.wav_load(DIR_PKG_WAV.."/hammer.wav") - wav_jump_up = common.wav_load(DIR_PKG_WAV.."/jump-up.wav") - wav_jump_down = common.wav_load(DIR_PKG_WAV.."/jump-down.wav") - wav_pin = common.wav_load(DIR_PKG_WAV.."/pin.wav") - wav_steps = {} - local i - for i=1,8 do - wav_steps[i] = common.wav_load(DIR_PKG_WAV.."/step"..i..".wav") - end -end - --- weapons -WPN_RIFLE = 1 - -weapon_models = {} - -weapons = { - [WPN_RIFLE] = function (plr) - local this = {} this.this = this - - this.cfg = { - dmg = { - head = 100, - body = 49, - legs = 33, - }, - - ammo_clip = 10, - ammo_reserve = 50, - time_fire = 1/2, - time_reload = 2.5, - - recoil_x = 0.0001, - recoil_y = -0.05, - - name = "Rifle" - } - - function this.restock() - this.ammo_clip = this.cfg.ammo_clip - this.ammo_reserve = this.cfg.ammo_reserve - end - - function this.reset() - this.t_fire = nil - this.t_reload = nil - this.reloading = false - this.restock() - end - - this.reset() - - local function prv_fire(sec_current) - local xlen, ylen, zlen - xlen, ylen, zlen = common.map_get_dims() - - if client then - tracer_add(plr.x,plr.y,plr.z, - plr.angy,plr.angx) - - client.wav_play_global(wav_rifle_shot, plr.x, plr.y, plr.z) - end - - local sya = math.sin(plr.angy) - local cya = math.cos(plr.angy) - local sxa = math.sin(plr.angx) - local cxa = math.cos(plr.angx) - local fwx,fwy,fwz - fwx,fwy,fwz = sya*cxa, sxa, cya*cxa - - -- perform a trace - local d,cx1,cy1,cz1,cx2,cy2,cz2 - d,cx1,cy1,cz1,cx2,cy2,cz2 - = trace_map_ray_dist(plr.x+sya*0.4,plr.y,plr.z+cya*0.4, fwx,fwy,fwz, 127.5) - d = d or 127.5 - - -- see if there's anyone we can kill - local hurt_idx = nil - local hurt_part = nil - local hurt_part_idx = 0 - local hurt_dist = d*d - local i,j - - for i=1,players.max do - local p = players[i] - if p and p ~= plr and p.alive then - local dx = p.x-plr.x - local dy = p.y-plr.y+0.1 - local dz = p.z-plr.z - - for j=1,3 do - local dd = dx*dx+dy*dy+dz*dz - - local dotk = dx*fwx+dy*fwy+dz*fwz - local dot = math.sqrt(dd-dotk*dotk) - if dot < 0.55 and dd < hurt_dist then - hurt_idx = i - hurt_dist = dd - hurt_part_idx = j - hurt_part = ({"head","body","legs"})[j] - - break - end - dy = dy + 1.0 - end - end - end - - if hurt_idx then - if server then - players[hurt_idx].gun_damage( - hurt_part, this.cfg.dmg[hurt_part], plr) - else - common.net_send(nil, common.net_pack("BBB" - , 0x13, hurt_idx, hurt_part_idx)) - end - else - if client then - common.net_send(nil, common.net_pack("BBB" - , 0x13, 0, 0)) - end - - if cx2 and cy2 <= ylen-3 then - bhealth_damage(cx2,cy2,cz2,MODE_BLOCK_DAMAGE_RIFLE) - end - end - - -- TODO: fire a tracer - - -- apply recoil - -- attempting to emulate classic behaviour provided i have it right - plr.recoil(sec_current, this.cfg.recoil_y, this.cfg.recoil_x) - end - - function this.reload() - if this.ammo_clip ~= this.cfg.ammo_clip then - if this.ammo_reserve ~= 0 then - if not this.reloading then - this.reloading = true - client.wav_play_global(wav_rifle_reload, plr.x, plr.y, plr.z) - common.net_send(nil, common.net_pack("BB", 0x1D, 0)) - plr.zooming = false - this.t_reload = nil - end end end - end - - function this.click(button, state) - if button == 1 then - -- LMB - if this.ammo_clip > 0 then - this.firing = state - else - this.firing = false - -- TODO: play sound - end - elseif button == 3 then - -- RMB - if hold_to_zoom then - plr.zooming = state - else - if state and not this.reloading then - plr.zooming = not plr.zooming - end - end - end - end - - function this.get_model() - return weapon_models[WPN_RIFLE] - end - - function this.draw(px, py, pz, ya, xa, ya2) - client.model_render_bone_global(this.get_model(), 0, - px, py, pz, ya, xa, ya2, 3) - end - - function this.tick(sec_current, sec_delta) - if this.reloading then - if not this.t_reload then - this.t_reload = sec_current + this.cfg.time_reload - end - - if sec_current >= this.t_reload then - local adelta = this.cfg.ammo_clip - this.ammo_clip - if adelta > this.ammo_reserve then - adelta = this.ammo_reserve - end - this.ammo_reserve = this.ammo_reserve - adelta - this.ammo_clip = this.ammo_clip + adelta - this.t_reload = nil - this.reloading = false - plr.arm_rest_right = 0 - else - local tremain = this.t_reload - sec_current - local telapsed = this.cfg.time_reload - tremain - local roffs = math.min(tremain,telapsed) - roffs = math.min(roffs,0.3)/0.3 - - plr.arm_rest_right = roffs - end - elseif this.firing and this.ammo_clip == 0 then - this.firing = false - elseif this.firing and ((not this.t_fire) or sec_current >= this.t_fire) then - prv_fire(sec_current) - - this.t_fire = this.t_fire or sec_current - this.t_fire = this.t_fire + this.cfg.time_fire - if this.t_fire < sec_current then - this.t_fire = sec_current - end - - this.ammo_clip = this.ammo_clip - 1 - - -- TODO: poll: do we want to require a new click per shot? - -- nope - rakiru - end - - if this.t_fire and this.t_fire < sec_current then - this.t_fire = nil - end - end - - return this - end, -} - -weapons_enabled = {} -weapons_enabled[WPN_RIFLE] = true - --- teams -teams = { - [0] = { - name = "Blue Master Race", - color_mdl = {16,32,128}, - color_chat = {0,0,255}, - }, - [1] = { - name = "Green Master Race", - color_mdl = {16,128,32}, - color_chat = {0,192,0}, - }, -} - -cpalette_base = { - 0x7F,0x7F,0x7F, - 0xFF,0x00,0x00, - 0xFF,0x7F,0x00, - 0xFF,0xFF,0x00, - 0x00,0xFF,0x00, - 0x00,0xFF,0xFF, - 0x00,0x00,0xFF, - 0xFF,0x00,0xFF, -} - -cpalette = {} -do - local i,j - for i=0,7 do - local r,g,b - r = cpalette_base[i*3+1] - g = cpalette_base[i*3+2] - b = cpalette_base[i*3+3] - for j=0,3 do - local cr = math.floor((r*j)/3) - local cg = math.floor((g*j)/3) - local cb = math.floor((b*j)/3) - cpalette[#cpalette+1] = {cr,cg,cb} - end - for j=1,4 do - local cr = r + math.floor(((255-r)*j)/4) - local cg = g + math.floor(((255-g)*j)/4) - local cb = b + math.floor(((255-b)*j)/4) - cpalette[#cpalette+1] = {cr,cg,cb} - end - end -end - -damage_blk = {} -players = {max = 32, current = 1} -intent = {} -nades = {head = 1, tail = 0} - -function sort_players() - players_sorted = {} - for k,v in ipairs(players) do - players_sorted[k] = v - end - table.sort(players_sorted, - function(x, y) - if x.score == y.score then - if x.kills == y.kills then - if x.deaths == y.deaths then - return x.pid < y.pid - end - return x.deaths < y.deaths - end - return x.kills > y.kills - end - return x.score > y.score - end - ) -end - -local players_mt = {} -function players_mt.__newindex(self, key, value) - rawset(self, key, value) - sort_players() -end +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +print("base dir:",common.base_dir) + +dofile("pkg/base/version.lua") + +-- base dir stuff +DIR_PKG_ROOT = DIR_PKG_ROOT or "pkg/base" +DIR_PKG_LIB = DIR_PKG_LIB or DIR_PKG_ROOT +DIR_PKG_PMF = DIR_PKG_PMF or DIR_PKG_ROOT.."/pmf" +DIR_PKG_GFX = DIR_PKG_GFX or DIR_PKG_ROOT.."/gfx" +DIR_PKG_WAV = DIR_PKG_WAV or DIR_PKG_ROOT.."/wav" +DIR_PKG_MAP = DIR_PKG_MAP or "pkg/maps" + +MAP_DEFAULT = MAP_DEFAULT or DIR_PKG_MAP.."/mesa.vxl" + +LIB_LIST = LIB_LIST or { + DIR_PKG_LIB.."/icegui/widgets.lua", + + DIR_PKG_LIB.."/lib_bits.lua", + DIR_PKG_LIB.."/lib_collect.lua", + DIR_PKG_LIB.."/lib_gui.lua", + DIR_PKG_LIB.."/lib_map.lua", + DIR_PKG_LIB.."/lib_namegen.lua", + DIR_PKG_LIB.."/lib_pmf.lua", + DIR_PKG_LIB.."/lib_sdlkey.lua", + DIR_PKG_LIB.."/lib_util.lua", + DIR_PKG_LIB.."/lib_vector.lua", + + DIR_PKG_LIB.."/obj_player.lua", + DIR_PKG_LIB.."/obj_intent.lua", + DIR_PKG_LIB.."/obj_nade.lua", +} + +-- load libs +local i +for i=1,#LIB_LIST do + local asdf_qwerty = i + i = nil + dofile(LIB_LIST[asdf_qwerty]) + i = asdf_qwerty +end +i = nil + + +-- mode stuff +MODE_DEBUG_SHOWBOXES = false +MODE_CHEAT_FLY = false + +MODE_AUTOCLIMB = true +MODE_AIRJUMP = false +MODE_SOFTCROUCH = true + +MODE_NADE_SPEED = 30.0 +MODE_NADE_STEP = 0.1 +MODE_NADE_FUSE = 3.0 +MODE_NADE_ADAMP = 0.5 +MODE_NADE_BDAMP = 1.0 +MODE_NADE_RANGE = 8.0 +MODE_NADE_DAMAGE = 500.0 + +MODE_MINIMAP_RCIRC = false +MODE_ENABLE_MINIMAP = true +MODE_MAP_TRACERS = false -- TODO! + +MODE_TILT_SLOWDOWN = false -- TODO! +MODE_TILT_DOWN_NOCLIMB = false -- TODO! + +MODE_DRUNKCAM_VELOCITY = false -- keep this off unless you want to throw up +MODE_DRUNKCAM_LOCALTURN = true -- this is the one you're looking for. +MODE_DRUNKCAM_CORRECTSPEED = 10.0 + +MODE_DELAY_SPADE_DIG = 1.0 +MODE_DELAY_SPADE_HIT = 0.25 +MODE_DELAY_BLOCK_BUILD = 0.5 +MODE_DELAY_TOOL_CHANGE = 0.2 +MODE_DELAY_NADE_THROW = 0.5 + +MODE_BLOCK_HEALTH = 100 +MODE_BLOCK_DAMAGE_SPADE = 34 +MODE_BLOCK_DAMAGE_RIFLE = 34 +MODE_BLOCK_REGEN_TIME = 15.0 +MODE_BLOCK_PLACE_IN_AIR = false --TODO: make this a server config variable, maybe godmode? + +MODE_RCIRC_LINGER = 60.0 +MODE_RESPAWN_TIME = 8.0 + +MODE_CHAT_LINGER = 15.0 +MODE_CHAT_MAX = 10 +MODE_CHAT_STRMAX = 102 + +-- scoring +SCORE_INTEL = 10 +SCORE_KILL = 1 +SCORE_TEAMKILL = -1 +SCORE_SUICIDE = -1 + +-- tools +TOOL_SPADE = 0 +TOOL_BLOCK = 1 +TOOL_GUN = 2 +TOOL_NADE = 3 + +-- sounds +if client then + client.wav_cube_size(0.5) + wav_rifle_shot = common.wav_load(DIR_PKG_WAV.."/rifle-shot.wav") + wav_rifle_reload = common.wav_load(DIR_PKG_WAV.."/rifle-reload.wav") + wav_whoosh = common.wav_load(DIR_PKG_WAV.."/whoosh.wav") + wav_buld = common.wav_load(DIR_PKG_WAV.."/buld.wav") + wav_grif = common.wav_load(DIR_PKG_WAV.."/grif.wav") + wav_hammer = common.wav_load(DIR_PKG_WAV.."/hammer.wav") + wav_jump_up = common.wav_load(DIR_PKG_WAV.."/jump-up.wav") + wav_jump_down = common.wav_load(DIR_PKG_WAV.."/jump-down.wav") + wav_pin = common.wav_load(DIR_PKG_WAV.."/pin.wav") + wav_steps = {} + local i + for i=1,8 do + wav_steps[i] = common.wav_load(DIR_PKG_WAV.."/step"..i..".wav") + end +end + +-- weapons +WPN_RIFLE = 1 + +weapon_models = {} + +weapons = { + [WPN_RIFLE] = function (plr) + local this = {} this.this = this + + this.cfg = { + dmg = { + head = 100, + body = 49, + legs = 33, + }, + + ammo_clip = 10, + ammo_reserve = 50, + time_fire = 1/2, + time_reload = 2.5, + + recoil_x = 0.0001, + recoil_y = -0.05, + + name = "Rifle" + } + + function this.restock() + this.ammo_clip = this.cfg.ammo_clip + this.ammo_reserve = this.cfg.ammo_reserve + end + + function this.reset() + this.t_fire = nil + this.t_reload = nil + this.reloading = false + this.restock() + end + + this.reset() + + local function prv_fire(sec_current) + local xlen, ylen, zlen + xlen, ylen, zlen = common.map_get_dims() + + if client then + tracer_add(plr.x,plr.y,plr.z, + plr.angy,plr.angx) + + client.wav_play_global(wav_rifle_shot, plr.x, plr.y, plr.z) + end + + local sya = math.sin(plr.angy) + local cya = math.cos(plr.angy) + local sxa = math.sin(plr.angx) + local cxa = math.cos(plr.angx) + local fwx,fwy,fwz + fwx,fwy,fwz = sya*cxa, sxa, cya*cxa + + -- perform a trace + local d,cx1,cy1,cz1,cx2,cy2,cz2 + d,cx1,cy1,cz1,cx2,cy2,cz2 + = trace_map_ray_dist(plr.x+sya*0.4,plr.y,plr.z+cya*0.4, fwx,fwy,fwz, 127.5) + d = d or 127.5 + + -- see if there's anyone we can kill + local hurt_idx = nil + local hurt_part = nil + local hurt_part_idx = 0 + local hurt_dist = d*d + local i,j + + for i=1,players.max do + local p = players[i] + if p and p ~= plr and p.alive then + local dx = p.x-plr.x + local dy = p.y-plr.y+0.1 + local dz = p.z-plr.z + + for j=1,3 do + local dd = dx*dx+dy*dy+dz*dz + + local dotk = dx*fwx+dy*fwy+dz*fwz + local dot = math.sqrt(dd-dotk*dotk) + if dot < 0.55 and dd < hurt_dist then + hurt_idx = i + hurt_dist = dd + hurt_part_idx = j + hurt_part = ({"head","body","legs"})[j] + + break + end + dy = dy + 1.0 + end + end + end + + if hurt_idx then + if server then + players[hurt_idx].gun_damage( + hurt_part, this.cfg.dmg[hurt_part], plr) + else + common.net_send(nil, common.net_pack("BBB" + , 0x13, hurt_idx, hurt_part_idx)) + end + else + if client then + common.net_send(nil, common.net_pack("BBB" + , 0x13, 0, 0)) + end + + if cx2 and cy2 <= ylen-3 then + bhealth_damage(cx2,cy2,cz2,MODE_BLOCK_DAMAGE_RIFLE) + end + end + + -- TODO: fire a tracer + + -- apply recoil + -- attempting to emulate classic behaviour provided i have it right + plr.recoil(sec_current, this.cfg.recoil_y, this.cfg.recoil_x) + end + + function this.reload() + if this.ammo_clip ~= this.cfg.ammo_clip then + if this.ammo_reserve ~= 0 then + if not this.reloading then + this.reloading = true + client.wav_play_global(wav_rifle_reload, plr.x, plr.y, plr.z) + common.net_send(nil, common.net_pack("BB", 0x1D, 0)) + plr.zooming = false + this.t_reload = nil + end end end + end + + function this.click(button, state) + if button == 1 then + -- LMB + if this.ammo_clip > 0 then + this.firing = state + else + this.firing = false + -- TODO: play sound + end + elseif button == 3 then + -- RMB + if hold_to_zoom then + plr.zooming = state + else + if state and not this.reloading then + plr.zooming = not plr.zooming + end + end + end + end + + function this.get_model() + return weapon_models[WPN_RIFLE] + end + + function this.draw(px, py, pz, ya, xa, ya2) + client.model_render_bone_global(this.get_model(), 0, + px, py, pz, ya, xa, ya2, 3) + end + + function this.tick(sec_current, sec_delta) + if this.reloading then + if not this.t_reload then + this.t_reload = sec_current + this.cfg.time_reload + end + + if sec_current >= this.t_reload then + local adelta = this.cfg.ammo_clip - this.ammo_clip + if adelta > this.ammo_reserve then + adelta = this.ammo_reserve + end + this.ammo_reserve = this.ammo_reserve - adelta + this.ammo_clip = this.ammo_clip + adelta + this.t_reload = nil + this.reloading = false + plr.arm_rest_right = 0 + else + local tremain = this.t_reload - sec_current + local telapsed = this.cfg.time_reload - tremain + local roffs = math.min(tremain,telapsed) + roffs = math.min(roffs,0.3)/0.3 + + plr.arm_rest_right = roffs + end + elseif this.firing and this.ammo_clip == 0 then + this.firing = false + elseif this.firing and ((not this.t_fire) or sec_current >= this.t_fire) then + prv_fire(sec_current) + + this.t_fire = this.t_fire or sec_current + this.t_fire = this.t_fire + this.cfg.time_fire + if this.t_fire < sec_current then + this.t_fire = sec_current + end + + this.ammo_clip = this.ammo_clip - 1 + + -- TODO: poll: do we want to require a new click per shot? + -- nope - rakiru + end + + if this.t_fire and this.t_fire < sec_current then + this.t_fire = nil + end + end + + return this + end, +} + +weapons_enabled = {} +weapons_enabled[WPN_RIFLE] = true + +-- teams +teams = { + [0] = { + name = "Blue Master Race", + color_mdl = {16,32,128}, + color_chat = {0,0,255}, + }, + [1] = { + name = "Green Master Race", + color_mdl = {16,128,32}, + color_chat = {0,192,0}, + }, +} + +cpalette_base = { + 0x7F,0x7F,0x7F, + 0xFF,0x00,0x00, + 0xFF,0x7F,0x00, + 0xFF,0xFF,0x00, + 0x00,0xFF,0x00, + 0x00,0xFF,0xFF, + 0x00,0x00,0xFF, + 0xFF,0x00,0xFF, +} + +cpalette = {} +do + local i,j + for i=0,7 do + local r,g,b + r = cpalette_base[i*3+1] + g = cpalette_base[i*3+2] + b = cpalette_base[i*3+3] + for j=0,3 do + local cr = math.floor((r*j)/3) + local cg = math.floor((g*j)/3) + local cb = math.floor((b*j)/3) + cpalette[#cpalette+1] = {cr,cg,cb} + end + for j=1,4 do + local cr = r + math.floor(((255-r)*j)/4) + local cg = g + math.floor(((255-g)*j)/4) + local cb = b + math.floor(((255-b)*j)/4) + cpalette[#cpalette+1] = {cr,cg,cb} + end + end +end + +damage_blk = {} +players = {max = 32, current = 1} +intent = {} +nades = {head = 1, tail = 0} + +function sort_players() + players_sorted = {} + for k,v in ipairs(players) do + players_sorted[k] = v + end + table.sort(players_sorted, + function(x, y) + if x.score == y.score then + if x.kills == y.kills then + if x.deaths == y.deaths then + return x.pid < y.pid + end + return x.deaths < y.deaths + end + return x.kills > y.kills + end + return x.score > y.score + end + ) +end + +local players_mt = {} +function players_mt.__newindex(self, key, value) + rawset(self, key, value) + sort_players() +end setmetatable(players, players_mt) \ No newline at end of file diff --git a/pkg/base/lib_map.lua b/pkg/base/lib_map.lua index 0d03e54..82f1f24 100644 --- a/pkg/base/lib_map.lua +++ b/pkg/base/lib_map.lua @@ -1,455 +1,473 @@ ---[[ - This file is part of Ice Lua Components. - - Ice Lua Components is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Ice Lua Components is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Ice Lua Components. If not, see . -]] - --- returns a list consisting of {t,r,g,b} tuplets -function map_pillar_raw_unpack(tpack) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - local t = {} - local i,j,y - i = 1 - y = 0 - - while true do - -- fill with air - while y < tpack[i+1] do - t[y+1] = nil - y = y + 1 - end - - -- fill with top data - j = i + 4 - while y <= tpack[i+2] do - t[y+1] = {tpack[j+3],tpack[j+2],tpack[j+1],tpack[j+0]} - y = y + 1 - j = j + 4 - end - - -- check if end - if tpack[i] == 0 then - -- fill the rest with invisible - while y < ylen do - t[y+1] = false - y = y + 1 - end - -- that's it - break - end - - local ntr = tpack[i]-1-(tpack[i+2]-tpack[i+1]+1) - i = i + 4*tpack[i] - ntr = tpack[i+3] - ntr - - -- fill with invisible - while y < ntr do - t[y+1] = false - y = y + 1 - end - - -- fill with bottom data - while y < tpack[i+3] do - t[y+1] = {tpack[j+3],tpack[j+2],tpack[j+1],tpack[j+0]} - y = y + 1 - j = j + 4 - end - end - - return t -end - -function map_pillar_raw_get(x,z) - return map_pillar_raw_unpack(common.map_pillar_get(x,z)) -end - -function map_pillar_raw_pack(t) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - local tpack = {} - local y,i - local rmode = 0 - local n,s,e,a - a = 0 - i = nil - y = 0 - - while true do - -- skip air - while t[y+1] == nil do - y = y + 1 - if y >= ylen then break end - end - if y >= ylen then break end - - if i then tpack[i] = n end - - -- allocate slot - i = #tpack+1 - tpack[i+0] = 0 - tpack[i+1] = y - tpack[i+2] = 0 - tpack[i+3] = a - - -- copy top run - n = 1 - while t[y+1] do - tpack[#tpack+1] = t[y+1][4] - tpack[#tpack+1] = t[y+1][3] - tpack[#tpack+1] = t[y+1][2] - tpack[#tpack+1] = t[y+1][1] - y = y + 1 - n = n + 1 - end - tpack[i+2] = y-1 - - -- skip dirt - while t[y+1] == false do - y = y + 1 - if y >= ylen then break end - end - if y >= ylen then break end - - -- build bottom run - while t[y+1] do - tpack[#tpack+1] = t[y+1][4] - tpack[#tpack+1] = t[y+1][3] - tpack[#tpack+1] = t[y+1][2] - tpack[#tpack+1] = t[y+1][1] - n = n + 1 - y = y + 1 - end - - a = y - end - - return tpack -end - -function map_pillar_raw_set(x,z,t) - local tpack = map_pillar_raw_pack(t) - - common.map_pillar_set(x,z,tpack) - - if img_overview and tpack[5] then - -- TODO: check for wrapping - local r,g,b - b = tpack[5] - g = tpack[6] - r = tpack[7] - local c = argb_split_to_merged(r,g,b) - common.img_pixel_set(img_overview, x, z, c) - end -end - -function map_block_aerate(x,y,z) - return ({ - 1, - 64+math.sin((x+z-y)*math.pi/4)*8, - 32-math.sin((x-z+y)*math.pi/4)*8, - 0 - }) -end - -function map_pillar_aerate(x,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - local t = map_pillar_raw_get(x,z) - local l = { - map_pillar_raw_get(x-1,z), - map_pillar_raw_get(x+1,z), - map_pillar_raw_get(x,z-1), - map_pillar_raw_get(x,z+1), - } - local y - - for y=1,ylen do - if t[y] then - if l[1][y] ~= nil and l[2][y] ~= nil - and l[3][y] ~= nil and l[4][y] ~= nil - and t[y-1] ~= nil and (y == ylen or t[y+1] ~= nil) then - t[y] = false - end - elseif t[y] == false then - if l[1][y] == nil or l[2][y] == nil - or l[3][y] == nil or l[4][y] == nil - or t[y-1] == nil or (y ~= ylen and t[y+1] == nil) then - t[y] = map_block_aerate(x,y-1,z) - end - end - end - - map_pillar_raw_set(x,z,t) -end - -function map_hashcoord3(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - return - (y % ylen) + ylen*((x % xlen) + xlen*(z % zlen)) -end - -function map_hashcoord2(x,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - return (x % xlen) - +xlen*(z % zlen) -end - -function map_chkdisbrk(x,y,z) - -- A* ftw - local loadq = { - {x-1,y,z}, - {x+1,y,z}, - {x,y-1,z}, - {x,y+1,z}, - {x,y,z-1}, - {x,y,z+1}, - } - local tmap = {} - local pmap = {} - local plist = {} - local ptag = {} - local ptaglist = {} - local nukeq = {} - - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - -- build chunks - local i,j - for i=1,#loadq do - local prio,tx,ty,tz - tx,ty,tz = loadq[i][1],loadq[i][2],loadq[i][3] - - if not pmap[map_hashcoord2(tx,tz)] then - pmap[map_hashcoord2(tx,tz)] = map_pillar_raw_get(tx,tz) - plist[#plist+1] = {tx,tz} - end - - if (not tmap[map_hashcoord3(tx,ty,tz)]) and pmap[map_hashcoord2(tx,tz)][ty+1] ~= nil then - local pq = collect_new_prioq(function(p,q) - return p[1] < q[1] - end) - - tmap[map_hashcoord3(tx,ty,tz)] = { - heur = -ty, - dist = 0, - i = i, - } - pq.push({-ty,tx,ty,tz}) - - local nukeasm = {} - while nukeasm and not pq.empty() do - local c = pq.pop() - prio,tx,ty,tz = c[1],c[2],c[3],c[4] - --print(prio,tx,ty,tz) - local tm = tmap[map_hashcoord3(tx,ty,tz)] - if prio <= tm.heur + tm.dist then - --print(i,prio,tx,ty,tz) - nukeasm[#nukeasm+1] = {tx,ty,tz} - if not pmap[map_hashcoord2(tx,tz)] then - pmap[map_hashcoord2(tx,tz)] = map_pillar_raw_get(tx,tz) - plist[#plist+1] = {tx,tz} - end - - local nb = { - {tx-1,ty,tz}, - {tx+1,ty,tz}, - {tx,ty-1,tz}, - {tx,ty+1,tz}, - {tx,ty,tz-1}, - {tx,ty,tz+1}, - } - - local dist = tm.dist+1 - for j=1,6 do - local cx,cy,cz = nb[j][1], nb[j][2], nb[j][3] - local cm = tmap[map_hashcoord3(cx,cy,cz)] - if cy == ylen or (cm and cm.i ~= i) then - --print("BAIL!") - nukeasm = nil - break - end - - if not pmap[map_hashcoord2(cx,cz)] then - pmap[map_hashcoord2(cx,cz)] = map_pillar_raw_get(cx,cz) - plist[#plist+1] = {cx,cz} - end - - if pmap[map_hashcoord2(cx,cz)][cy+1] ~= nil then - local heur = -cy - if not cm then - cm = { - heur = heur, - dist = dist, - i = i, - } - tmap[map_hashcoord3(cx,cy,cz)] = cm - pq.push({heur+dist,cx,cy,cz}) - else - if cm.heur+cm.dist > heur+dist then - cm.heur = heur - cm.dist = dist - pq.push({heur+dist,cx,cy,cz}) - end - end - end - end - end - end - - if nukeasm then - nukeq[#nukeq+1] = nukeasm - --print(#nukeq,#nukeasm) - end - end - end - - -- nuke it all - -- TODO: assemble falling PMFs and drop the buggers - local brokestuff = false - for i=1,#nukeq do - local tx,ty,tz - local nl = nukeq[i] - if #nl > 0 then brokestuff = true end - for j=1,#nl do - local c = nl[j] - tx,ty,tz = c[1],c[2],c[3] - if not ptag[map_hashcoord2(tx,tz)] then - ptag[map_hashcoord2(tx,tz)] = true - ptaglist[#ptaglist+1] = {tx,tz} - end - pmap[map_hashcoord2(tx,tz)][ty+1] = nil - end - end - - if brokestuff and client then - client.wav_play_global(wav_grif,x+0.5,y+0.5,z+0.5) - end - - -- apply nukings - local nptag = {} - local nptaglist = {} - for i=1,#ptaglist do - local tx,tz - local c = ptaglist[i] - tx,tz = c[1], c[2] - map_pillar_raw_set(tx,tz,pmap[map_hashcoord2(tx,tz)]) - - if not nptag[map_hashcoord2(tx,tz)] then - nptag[map_hashcoord2(tx,tz)] = true - nptaglist[#nptaglist+1] = {tx,tz} - end - end - - -- aerate - for i=1,#nptaglist do - local tx,tz - local c = nptaglist[i] - tx,tz = c[1], c[2] - - map_pillar_aerate(tx,tz) - end -end - -function map_block_get(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if y < 0 or y >= ylen then return end - - local t = map_pillar_raw_get(x,z) - return t[y+1] -end - -function map_block_set(x,y,z,typ,r,g,b) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if y < 0 or y >= ylen then return end - - local t = map_pillar_raw_get(x,z) - t[y+1] = {typ, r, g, b} - map_pillar_raw_set(x,z,t) - - map_pillar_aerate(x,z) - map_pillar_aerate(x-1,z) - map_pillar_aerate(x+1,z) - map_pillar_aerate(x,z-1) - map_pillar_aerate(x,z+1) -end - -function map_block_paint(x,y,z,typ,r,g,b) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if y < 0 or y >= ylen then return end - - local t = map_pillar_raw_get(x,z) - if t[y+1] then - t[y+1] = {typ, r, g, b} - map_pillar_raw_set(x,z,t) - end -end - -function map_block_break(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if y < 0 or y >= ylen-1 then return false end - - local t = map_pillar_raw_get(x,z) - if t[y+1] == nil then return false end - t[y+1] = nil - map_pillar_raw_set(x,z,t) - - map_pillar_aerate(x,z) - map_pillar_aerate(x-1,z) - map_pillar_aerate(x+1,z) - map_pillar_aerate(x,z-1) - map_pillar_aerate(x,z+1) - - map_chkdisbrk(x,y,z) - - return true -end - -function map_block_delete(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if y < 0 or y >= ylen-1 then return end - - local t = map_pillar_raw_get(x,z) - t[y+1] = nil - map_pillar_raw_set(x,z,t) - - map_pillar_aerate(x,z) - map_pillar_aerate(x-1,z) - map_pillar_aerate(x+1,z) - map_pillar_aerate(x,z-1) - map_pillar_aerate(x,z+1) -end - -function map_block_pick(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - if x < 0 or x >= xlen then return end - if y < 0 or y >= ylen then return end - if z < 0 or z >= zlen then return end - - local t = map_pillar_raw_get(x,z) - local c = t[y+1] - - return c[1],c[2],c[3],c[4] -end +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- returns a list consisting of {t,r,g,b} tuplets +function map_pillar_raw_unpack(tpack) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + local t = {} + local i,j,y + i = 1 + y = 0 + + while true do + -- fill with air + while y < tpack[i+1] do + t[y+1] = nil + y = y + 1 + end + + -- fill with top data + j = i + 4 + while y <= tpack[i+2] do + t[y+1] = {tpack[j+3],tpack[j+2],tpack[j+1],tpack[j+0]} + y = y + 1 + j = j + 4 + end + + -- check if end + if tpack[i] == 0 then + -- fill the rest with invisible + while y < ylen do + t[y+1] = false + y = y + 1 + end + -- that's it + break + end + + local ntr = tpack[i]-1-(tpack[i+2]-tpack[i+1]+1) + i = i + 4*tpack[i] + ntr = tpack[i+3] - ntr + + -- fill with invisible + while y < ntr do + t[y+1] = false + y = y + 1 + end + + -- fill with bottom data + while y < tpack[i+3] do + t[y+1] = {tpack[j+3],tpack[j+2],tpack[j+1],tpack[j+0]} + y = y + 1 + j = j + 4 + end + end + + return t +end + +function map_pillar_raw_get(x,z) + return map_pillar_raw_unpack(common.map_pillar_get(x,z)) +end + +function map_pillar_raw_pack(t) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + local tpack = {} + local y,i + local rmode = 0 + local n,s,e,a + a = 0 + i = nil + y = 0 + + while true do + -- skip air + while t[y+1] == nil do + y = y + 1 + if y >= ylen then break end + end + if y >= ylen then break end + + if i then tpack[i] = n end + + -- allocate slot + i = #tpack+1 + tpack[i+0] = 0 + tpack[i+1] = y + tpack[i+2] = 0 + tpack[i+3] = a + + -- copy top run + n = 1 + while t[y+1] do + tpack[#tpack+1] = t[y+1][4] + tpack[#tpack+1] = t[y+1][3] + tpack[#tpack+1] = t[y+1][2] + tpack[#tpack+1] = t[y+1][1] + y = y + 1 + n = n + 1 + end + tpack[i+2] = y-1 + + -- skip dirt + while t[y+1] == false do + y = y + 1 + if y >= ylen then break end + end + if y >= ylen then break end + + -- build bottom run + while t[y+1] do + tpack[#tpack+1] = t[y+1][4] + tpack[#tpack+1] = t[y+1][3] + tpack[#tpack+1] = t[y+1][2] + tpack[#tpack+1] = t[y+1][1] + n = n + 1 + y = y + 1 + end + + a = y + end + + return tpack +end + +function map_pillar_raw_set(x,z,t) + local tpack = map_pillar_raw_pack(t) + + common.map_pillar_set(x,z,tpack) + + if img_overview and tpack[5] then + -- TODO: check for wrapping + local r,g,b + b = tpack[5] + g = tpack[6] + r = tpack[7] + local c = argb_split_to_merged(r,g,b) + common.img_pixel_set(img_overview, x, z, c) + end +end + +function map_block_aerate(x,y,z) + return ({ + 1, + 64+math.sin((x+z-y)*math.pi/4)*8, + 32-math.sin((x-z+y)*math.pi/4)*8, + 0 + }) +end + +function map_pillar_aerate(x,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + local t = map_pillar_raw_get(x,z) + local l = { + map_pillar_raw_get(x-1,z), + map_pillar_raw_get(x+1,z), + map_pillar_raw_get(x,z-1), + map_pillar_raw_get(x,z+1), + } + local y + + for y=1,ylen do + if t[y] then + if l[1][y] ~= nil and l[2][y] ~= nil + and l[3][y] ~= nil and l[4][y] ~= nil + and t[y-1] ~= nil and (y == ylen or t[y+1] ~= nil) then + t[y] = false + end + elseif t[y] == false then + if l[1][y] == nil or l[2][y] == nil + or l[3][y] == nil or l[4][y] == nil + or t[y-1] == nil or (y ~= ylen and t[y+1] == nil) then + t[y] = map_block_aerate(x,y-1,z) + end + end + end + + map_pillar_raw_set(x,z,t) +end + +function map_hashcoord3(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + return + (y % ylen) + ylen*((x % xlen) + xlen*(z % zlen)) +end + +function map_hashcoord2(x,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + return (x % xlen) + +xlen*(z % zlen) +end + +function map_chkdisbrk(x,y,z) + -- A* ftw + local loadq = { + {x-1,y,z}, + {x+1,y,z}, + {x,y-1,z}, + {x,y+1,z}, + {x,y,z-1}, + {x,y,z+1}, + } + local tmap = {} + local pmap = {} + local plist = {} + local ptag = {} + local ptaglist = {} + local nukeq = {} + + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + -- build chunks + local i,j + for i=1,#loadq do + local prio,tx,ty,tz + tx,ty,tz = loadq[i][1],loadq[i][2],loadq[i][3] + + if not pmap[map_hashcoord2(tx,tz)] then + pmap[map_hashcoord2(tx,tz)] = map_pillar_raw_get(tx,tz) + plist[#plist+1] = {tx,tz} + end + + if (not tmap[map_hashcoord3(tx,ty,tz)]) and pmap[map_hashcoord2(tx,tz)][ty+1] ~= nil then + local pq = collect_new_prioq(function(p,q) + return p[1] < q[1] + end) + + tmap[map_hashcoord3(tx,ty,tz)] = { + heur = -ty, + dist = 0, + i = i, + } + pq.push({-ty,tx,ty,tz}) + + local nukeasm = {} + while nukeasm and not pq.empty() do + local c = pq.pop() + prio,tx,ty,tz = c[1],c[2],c[3],c[4] + --print(prio,tx,ty,tz) + local tm = tmap[map_hashcoord3(tx,ty,tz)] + if prio <= tm.heur + tm.dist then + --print(i,prio,tx,ty,tz) + nukeasm[#nukeasm+1] = {tx,ty,tz} + if not pmap[map_hashcoord2(tx,tz)] then + pmap[map_hashcoord2(tx,tz)] = map_pillar_raw_get(tx,tz) + plist[#plist+1] = {tx,tz} + end + + local nb = { + {tx-1,ty,tz}, + {tx+1,ty,tz}, + {tx,ty-1,tz}, + {tx,ty+1,tz}, + {tx,ty,tz-1}, + {tx,ty,tz+1}, + } + + local dist = tm.dist+1 + for j=1,6 do + local cx,cy,cz = nb[j][1], nb[j][2], nb[j][3] + local cm = tmap[map_hashcoord3(cx,cy,cz)] + if cy == ylen or (cm and cm.i ~= i) then + --print("BAIL!") + nukeasm = nil + break + end + + if not pmap[map_hashcoord2(cx,cz)] then + pmap[map_hashcoord2(cx,cz)] = map_pillar_raw_get(cx,cz) + plist[#plist+1] = {cx,cz} + end + + if pmap[map_hashcoord2(cx,cz)][cy+1] ~= nil then + local heur = -cy + if not cm then + cm = { + heur = heur, + dist = dist, + i = i, + } + tmap[map_hashcoord3(cx,cy,cz)] = cm + pq.push({heur+dist,cx,cy,cz}) + else + if cm.heur+cm.dist > heur+dist then + cm.heur = heur + cm.dist = dist + pq.push({heur+dist,cx,cy,cz}) + end + end + end + end + end + end + + if nukeasm then + nukeq[#nukeq+1] = nukeasm + --print(#nukeq,#nukeasm) + end + end + end + + -- nuke it all + -- TODO: assemble falling PMFs and drop the buggers + local brokestuff = false + for i=1,#nukeq do + local tx,ty,tz + local nl = nukeq[i] + if #nl > 0 then brokestuff = true end + for j=1,#nl do + local c = nl[j] + tx,ty,tz = c[1],c[2],c[3] + if not ptag[map_hashcoord2(tx,tz)] then + ptag[map_hashcoord2(tx,tz)] = true + ptaglist[#ptaglist+1] = {tx,tz} + end + pmap[map_hashcoord2(tx,tz)][ty+1] = nil + end + end + + if brokestuff and client then + client.wav_play_global(wav_grif,x+0.5,y+0.5,z+0.5) + end + + -- apply nukings + local nptag = {} + local nptaglist = {} + for i=1,#ptaglist do + local tx,tz + local c = ptaglist[i] + tx,tz = c[1], c[2] + map_pillar_raw_set(tx,tz,pmap[map_hashcoord2(tx,tz)]) + + if not nptag[map_hashcoord2(tx,tz)] then + nptag[map_hashcoord2(tx,tz)] = true + nptaglist[#nptaglist+1] = {tx,tz} + end + end + + -- aerate + for i=1,#nptaglist do + local tx,tz + local c = nptaglist[i] + tx,tz = c[1], c[2] + + map_pillar_aerate(tx,tz) + end +end + +function map_block_get(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if y < 0 or y >= ylen then return end + + local t = map_pillar_raw_get(x,z) + return t[y+1] +end + +function map_block_set(x,y,z,typ,r,g,b) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if y < 0 or y >= ylen then return end + + local t = map_pillar_raw_get(x,z) + t[y+1] = {typ, r, g, b} + map_pillar_raw_set(x,z,t) + + map_pillar_aerate(x,z) + map_pillar_aerate(x-1,z) + map_pillar_aerate(x+1,z) + map_pillar_aerate(x,z-1) + map_pillar_aerate(x,z+1) +end + +function map_block_paint(x,y,z,typ,r,g,b) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if y < 0 or y >= ylen then return end + + local t = map_pillar_raw_get(x,z) + if t[y+1] then + t[y+1] = {typ, r, g, b} + map_pillar_raw_set(x,z,t) + end +end + +function map_block_break(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if y < 0 or y >= ylen-1 then return false end + + local t = map_pillar_raw_get(x,z) + if t[y+1] == nil then return false end + t[y+1] = nil + map_pillar_raw_set(x,z,t) + + map_pillar_aerate(x,z) + map_pillar_aerate(x-1,z) + map_pillar_aerate(x+1,z) + map_pillar_aerate(x,z-1) + map_pillar_aerate(x,z+1) + + map_chkdisbrk(x,y,z) + + return true +end + +function map_block_delete(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if y < 0 or y >= ylen-1 then return end + + local t = map_pillar_raw_get(x,z) + t[y+1] = nil + map_pillar_raw_set(x,z,t) + + map_pillar_aerate(x,z) + map_pillar_aerate(x-1,z) + map_pillar_aerate(x+1,z) + map_pillar_aerate(x,z-1) + map_pillar_aerate(x,z+1) +end + +function map_block_pick(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + if x < 0 or x >= xlen then return end + if y < 0 or y >= ylen then return end + if z < 0 or z >= zlen then return end + + local t = map_pillar_raw_get(x,z) + local c = t[y+1] + + if c==nil then error(x..","..y..","..z) end + + return c[1],c[2],c[3],c[4] +end + +--checks for neighbors +function map_is_buildable(x, y, z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + --warning! a long condition + if map_block_get(x,y,z) == nil then + if map_block_get(x + 1,y,z) ~= nil or map_block_get(x - 1,y,z) ~= nil or map_block_get(x,y + 1,z) ~= nil or map_block_get(x,y - 1,z) ~= nil or map_block_get(x,y,z - 1) ~= nil or map_block_get(x,y,z + 1) ~= nil then + if x >=0 and x < xlen and y >= 0 and y < ylen - 2 and z >= 0 and z < zlen then + return true; + end + end + else + return false; + end +end \ No newline at end of file diff --git a/pkg/base/lib_vector.lua b/pkg/base/lib_vector.lua index ae93e50..61c1619 100644 --- a/pkg/base/lib_vector.lua +++ b/pkg/base/lib_vector.lua @@ -1,365 +1,372 @@ ---[[ - This file is part of Ice Lua Components. - - Ice Lua Components is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Ice Lua Components is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Ice Lua Components. If not, see . -]] - -function vcross(x1,y1,z1,x2,y2,z2) - return y1*z2 - z1*y2 - , z1*x2 - x1*z2 - , x1*y2 - y1*x2 -end - -function vdot(x1,y1,z1,x2,y2,z2) - return x1*x2 + y1*y2 + z1*z2 -end - -function vlen2(x,y,z) - return x*x + y*y + z*z -end - -function vlen(x,y,z) - return math.sqrt(vlen2(x,y,z)) -end - -function vnorm(x,y,z) - local d = math.max(0.0000001,vlen(x,y,z)) - return x/d, y/d, z/d -end - -function vrotate(theta,x,y,z,bx,by,bz) - -- glRotate as specified by SGI :D - bx,by,bz = vnorm(bx,by,bz) - - -- S = [ 0 -z y ] - -- [ z 0 -x ] - -- [ -y x 0 ] - -- R = uuT + cosO (I - uuT) + sinO S - -- alternatively - -- R = uuT * (1 - cosO) + IcosO + sinO S - - local ct = math.cos(theta) - local st = math.sin(theta) - - return - x*(bx*bx*(1-ct)+ct) + y*(bx*by*(1-ct) + st*-bz) + z*(bx*bz*(1-ct) + st*by), - x*(by*bx*(1-ct) + st*bz) + y*(by*by*(1-ct)*(1-ct)+ct) + z*(by*bz*(1-ct) + st*-bx), - x*(bz*bx*(1-ct) + st*-by) + y*(bz*by*(1-ct) + st*bx) + z*(bz*bz*(1-ct)+ct) -end - -function trace_gap(x,y,z) - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - local l = common.map_pillar_get(math.floor(x), math.floor(z)) - i = 1 - local h1,h2 - h1 = nil - while true do - h2 = l[i+1] - if h2 == ylen-1 then h2 = ylen end - if y < l[i+1] or l[i] == 0 then return h1, h2 end - i = i + l[i]*4 - if y < l[i+3] then return h1, h2 end - h1 = l[i+3] - h2 = l[i+1] - end -end - -function box_is_clear(x1,y1,z1,x2,y2,z2,canwrap) - local x,z,i - - x1 = math.floor(x1) - y1 = math.floor(y1) - z1 = math.floor(z1) - x2 = math.floor(x2) - y2 = math.floor(y2) - z2 = math.floor(z2) - - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - if not canwrap then - if x1 < 0 or z1 < 0 then - return false - elseif x2 >= xlen or z2 >= zlen then - return false - end - end - - for z=z1,z2 do - for x=x1,x2 do - local l = common.map_pillar_get(x, z) - i = 1 - while true do - if l[i+1] == ylen-1 and y2 < ylen then break end - if y2 < l[i+1] then break end - if l[i] == 0 then return false end - i = i + l[i]*4 - if y1 < l[i+3] then return false end - end - end - end - - return true -end - -function trace_map_ray_dist(x1,y1,z1, vx,vy,vz, maxdist) - local function depsilon(d) - if d < 0.0000001 then - return 0.0000001 - else - return d - end - end - - local xlen,ylen,zlen - xlen,ylen,zlen = common.map_get_dims() - - -- offsets - local fx,fy,fz - if vx < 0 then fx = bx1 else fx = bx2 end - if vy < 0 then fy = by1 else fy = by2 end - if vz < 0 then fz = bz1 else fz = bz2 end - - -- direction - local gx,gy,gz - if vx < 0 then gx = -1 else gx = 1 end - if vy < 0 then gy = -1 else gy = 1 end - if vz < 0 then gz = -1 else gz = 1 end - vx = vx * gx - vy = vy * gy - vz = vz * gz - - -- cell - local cx,cy,cz - cx = math.floor(x1) - cy = math.floor(y1) - cz = math.floor(z1) - - -- subpos - local sx,sy,sz - sx = x1-cx - sy = y1-cy - sz = z1-cz - if gx >= 0 then sx = 1-sx end - if gy >= 0 then sy = 1-sy end - if gz >= 0 then sz = 1-sz end - - local dist = 0 - local pillar, npillar - npillar = common.map_pillar_get(cx,cz) - pillar = npillar - - while true do - local tx = sx/depsilon(vx) - local ty = sy/depsilon(vy) - local tz = sz/depsilon(vz) - local t,d - local ncx,ncy,ncz - ncx,ncy,ncz = cx,cy,cz - - if tx < ty and tx < tz then - t = tx - d = 0 - ncx = cx + gx - npillar = common.map_pillar_get(ncx,ncz) - elseif ty < tx and ty < tz then - t = ty - d = 1 - ncy = cy + gy - else - t = tz - d = 2 - ncz = cz + gz - npillar = common.map_pillar_get(ncx,ncz) - end - - dist = dist + t - if dist > maxdist then return nil, nil, nil, nil, nil, nil, nil end - - local i=1 - while true do - if ncy < npillar[i+1] then break end - if npillar[i] == 0 then return dist, cx, cy, cz, ncx, ncy, ncz end - i = i + npillar[i]*4 - if ncy < npillar[i+3] then return dist, cx, cy, cz, ncx, ncy, ncz end - end - - sx = sx - vx*t - sy = sy - vy*t - sz = sz - vz*t - - cx,cy,cz = ncx,ncy,ncz - - if d == 0 then sx = 1 - elseif d == 1 then sy = 1 - else sz = 1 end - - pillar = npillar - end -end - -function trace_map_box(x1,y1,z1, x2,y2,z2, bx1,by1,bz1, bx2,by2,bz2, canwrap) - local function depsilon(d) - if d < 0.0000001 then - return 0.0000001 - else - return d - end - end - - -- delta - local dx,dy,dz - dx = x2-x1 - dy = y2-y1 - dz = z2-z1 - - -- offsets - local fx,fy,fz - if dx < 0 then fx = bx1 else fx = bx2 end - if dy < 0 then fy = by1 else fy = by2 end - if dz < 0 then fz = bz1 else fz = bz2 end - - -- direction - local gx,gy,gz - if dx < 0 then gx = -1 else gx = 1 end - if dy < 0 then gy = -1 else gy = 1 end - if dz < 0 then gz = -1 else gz = 1 end - dx = dx * gx - dy = dy * gy - dz = dz * gz - - -- combined box size - local bcx,bcy,bcz - bcx = (bx2-bx1) - bcy = (by2-by1) - bcz = (bz2-bz1) - - -- top left offset (note, incorrect name!) - local tlx,tly,tlz - if gx >= 0 then tlx = 0.999 else tlx = 0.001 end - if gy >= 0 then tly = 0.999 else tly = 0.001 end - if gz >= 0 then tlz = 0.999 else tlz = 0.001 end - - -- apply offset - x1 = x1 + fx - y1 = y1 + fy - z1 = z1 + fz - bx1 = bx1 - fx - by1 = by1 - fy - bz1 = bz1 - fz - bx2 = bx2 - fx - by2 = by2 - fy - bz2 = bz2 - fz - - -- cell - local cx,cy,cz - cx = math.floor(x1) - cy = math.floor(y1) - cz = math.floor(z1) - - -- target cell - local tcx,tcy,tcz - tcx = math.floor(x2+fx+gx*0.002) - tcy = math.floor(y2+fy+gy*0.002) - tcz = math.floor(z2+fz+gz*0.002) - - -- sub deltas - local sx, sy, sz - sx = (x1 % 1.0) - 0.001 - sy = (y1 % 1.0) - 0.001 - sz = (z1 % 1.0) - 0.001 - if gx >= 0 then sx = 1-sx end - if gy >= 0 then sy = 1-sy end - if gz >= 0 then sz = 1-sz end - - -- restricted x/y/z - local rx,ry,rz - rx = nil - ry = nil - rz = nil - - -- TODO: unset these when another boundary is crossed - - local i - local iend = ( - math.abs(tcx-cx) - + math.abs(tcy-cy) - + math.abs(tcz-cz) - ) - - for i=1,iend do - -- get the time it takes to hit the boundary - local tx = sx/depsilon(dx) - local ty = sy/depsilon(dy) - local tz = sz/depsilon(dz) - - local t, d, ck - - if tx < ty and tx < tz then - -- X first - d = 0 - t = tx - elseif ty < tx and ty < tz then - -- Y first - d = 1 - t = ty - else - -- Z first - d = 2 - t = tz - end - - sx = sx - t*dx - sy = sy - t*dy - sz = sz - t*dz - x1 = rx or x1 + t*dx*gx - y1 = ry or y1 + t*dy*gy - z1 = rz or z1 + t*dz*gz - - if d == 0 then - -- X first - sx = 1.0 - ck = rx or box_is_clear(cx+gx,y1+by1,z1+bz1,cx+gx,y1+by2,z1+bz2,canwrap) - if not ck then rx = cx + tlx end - if not rx then cx = cx + gx end - elseif d == 1 then - -- Y first - sy = 1.0 - ck = ry or box_is_clear(x1+bx1,cy+gy,z1+bz1,x1+bx2,cy+gy,z1+bz2,canwrap) - if not ck then ry = cy + tly end - if not ry then cy = cy + gy end - else - -- Z first - sz = 1.0 - ck = rz or box_is_clear(x1+bx1,y1+by1,cz+gz,x1+bx2,y1+by2,cz+gz,canwrap) - if not ck then rz = cz + tlz end - if not rz then cz = cz + gz end - end - - --if not ck then return x1-bx1, y1-by1, z1-bz1 end - end - -- - if rx then rx = rx - fx end - if ry then ry = ry - fy end - if rz then rz = rz - fz end - - return rx or x2, ry or y2, rz or z2 -end - -function isect_line_sphere(x1,y1,z1,fx,fy,fz,x2,y2,z2) - -end - +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +function vcross(x1,y1,z1,x2,y2,z2) + return y1*z2 - z1*y2 + , z1*x2 - x1*z2 + , x1*y2 - y1*x2 +end + +function vdot(x1,y1,z1,x2,y2,z2) + return x1*x2 + y1*y2 + z1*z2 +end + +function vlen2(x,y,z) + return x*x + y*y + z*z +end + +function vlen(x,y,z) + return math.sqrt(vlen2(x,y,z)) +end + +function vnorm(x,y,z) + local d = math.max(0.0000001,vlen(x,y,z)) + return x/d, y/d, z/d +end + +function vrotate(theta,x,y,z,bx,by,bz) + -- glRotate as specified by SGI :D + bx,by,bz = vnorm(bx,by,bz) + + -- S = [ 0 -z y ] + -- [ z 0 -x ] + -- [ -y x 0 ] + -- R = uuT + cosO (I - uuT) + sinO S + -- alternatively + -- R = uuT * (1 - cosO) + IcosO + sinO S + + local ct = math.cos(theta) + local st = math.sin(theta) + + return + x*(bx*bx*(1-ct)+ct) + y*(bx*by*(1-ct) + st*-bz) + z*(bx*bz*(1-ct) + st*by), + x*(by*bx*(1-ct) + st*bz) + y*(by*by*(1-ct)*(1-ct)+ct) + z*(by*bz*(1-ct) + st*-bx), + x*(bz*bx*(1-ct) + st*-by) + y*(bz*by*(1-ct) + st*bx) + z*(bz*bz*(1-ct)+ct) +end + +function trace_gap(x,y,z) + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + local l = common.map_pillar_get(math.floor(x), math.floor(z)) + i = 1 + local h1,h2 + h1 = nil + while true do + h2 = l[i+1] + if h2 == ylen-1 then h2 = ylen end + if y < l[i+1] or l[i] == 0 then return h1, h2 end + i = i + l[i]*4 + if y < l[i+3] then return h1, h2 end + h1 = l[i+3] + h2 = l[i+1] + end +end + +function box_is_clear(x1,y1,z1,x2,y2,z2,canwrap) + local x,z,i + + x1 = math.floor(x1) + y1 = math.floor(y1) + z1 = math.floor(z1) + x2 = math.floor(x2) + y2 = math.floor(y2) + z2 = math.floor(z2) + + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + if not canwrap then + if x1 < 0 or z1 < 0 then + return false + elseif x2 >= xlen or z2 >= zlen then + return false + end + end + + for z=z1,z2 do + for x=x1,x2 do + local l = common.map_pillar_get(x, z) + i = 1 + while true do + if l[i+1] == ylen-1 and y2 < ylen then break end + if y2 < l[i+1] then break end + if l[i] == 0 then return false end + i = i + l[i]*4 + if y1 < l[i+3] then return false end + end + end + end + + return true +end + +function trace_map_ray_dist(x1,y1,z1, vx,vy,vz, maxdist, nil_on_maxdist) + if nil_on_maxdist == nil then nil_on_maxdist = true end + + local function depsilon(d) + if d < 0.0000001 then + return 0.0000001 + else + return d + end + end + + local xlen,ylen,zlen + xlen,ylen,zlen = common.map_get_dims() + + -- offsets + local fx,fy,fz + if vx < 0 then fx = bx1 else fx = bx2 end + if vy < 0 then fy = by1 else fy = by2 end + if vz < 0 then fz = bz1 else fz = bz2 end + + -- direction + local gx,gy,gz + if vx < 0 then gx = -1 else gx = 1 end + if vy < 0 then gy = -1 else gy = 1 end + if vz < 0 then gz = -1 else gz = 1 end + vx = vx * gx + vy = vy * gy + vz = vz * gz + + -- cell + local cx,cy,cz + cx = math.floor(x1) + cy = math.floor(y1) + cz = math.floor(z1) + + -- subpos + local sx,sy,sz + sx = x1-cx + sy = y1-cy + sz = z1-cz + if gx >= 0 then sx = 1-sx end + if gy >= 0 then sy = 1-sy end + if gz >= 0 then sz = 1-sz end + + local dist = 0 + local pillar, npillar + npillar = common.map_pillar_get(cx,cz) + pillar = npillar + + while true do + local tx = sx/depsilon(vx) + local ty = sy/depsilon(vy) + local tz = sz/depsilon(vz) + local t,d + local ncx,ncy,ncz + ncx,ncy,ncz = cx,cy,cz + + if tx < ty and tx < tz then + t = tx + d = 0 + ncx = cx + gx + npillar = common.map_pillar_get(ncx,ncz) + elseif ty < tx and ty < tz then + t = ty + d = 1 + ncy = cy + gy + else + t = tz + d = 2 + ncz = cz + gz + npillar = common.map_pillar_get(ncx,ncz) + end + + dist = dist + t + + if dist > maxdist and nil_on_maxdist then + return nil, nil, nil, nil, nil, nil, nil + elseif dist > maxdist and not nil_on_maxdist then + return dist, cx, cy, cz, ncx, ncy, ncz + end + + local i=1 + while true do + if ncy < npillar[i+1] then break end + if npillar[i] == 0 then return dist, cx, cy, cz, ncx, ncy, ncz end + i = i + npillar[i]*4 + if ncy < npillar[i+3] then return dist, cx, cy, cz, ncx, ncy, ncz end + end + + sx = sx - vx*t + sy = sy - vy*t + sz = sz - vz*t + + cx,cy,cz = ncx,ncy,ncz + + if d == 0 then sx = 1 + elseif d == 1 then sy = 1 + else sz = 1 end + + pillar = npillar + end +end + +function trace_map_box(x1,y1,z1, x2,y2,z2, bx1,by1,bz1, bx2,by2,bz2, canwrap) + local function depsilon(d) + if d < 0.0000001 then + return 0.0000001 + else + return d + end + end + + -- delta + local dx,dy,dz + dx = x2-x1 + dy = y2-y1 + dz = z2-z1 + + -- offsets + local fx,fy,fz + if dx < 0 then fx = bx1 else fx = bx2 end + if dy < 0 then fy = by1 else fy = by2 end + if dz < 0 then fz = bz1 else fz = bz2 end + + -- direction + local gx,gy,gz + if dx < 0 then gx = -1 else gx = 1 end + if dy < 0 then gy = -1 else gy = 1 end + if dz < 0 then gz = -1 else gz = 1 end + dx = dx * gx + dy = dy * gy + dz = dz * gz + + -- combined box size + local bcx,bcy,bcz + bcx = (bx2-bx1) + bcy = (by2-by1) + bcz = (bz2-bz1) + + -- top left offset (note, incorrect name!) + local tlx,tly,tlz + if gx >= 0 then tlx = 0.999 else tlx = 0.001 end + if gy >= 0 then tly = 0.999 else tly = 0.001 end + if gz >= 0 then tlz = 0.999 else tlz = 0.001 end + + -- apply offset + x1 = x1 + fx + y1 = y1 + fy + z1 = z1 + fz + bx1 = bx1 - fx + by1 = by1 - fy + bz1 = bz1 - fz + bx2 = bx2 - fx + by2 = by2 - fy + bz2 = bz2 - fz + + -- cell + local cx,cy,cz + cx = math.floor(x1) + cy = math.floor(y1) + cz = math.floor(z1) + + -- target cell + local tcx,tcy,tcz + tcx = math.floor(x2+fx+gx*0.002) + tcy = math.floor(y2+fy+gy*0.002) + tcz = math.floor(z2+fz+gz*0.002) + + -- sub deltas + local sx, sy, sz + sx = (x1 % 1.0) - 0.001 + sy = (y1 % 1.0) - 0.001 + sz = (z1 % 1.0) - 0.001 + if gx >= 0 then sx = 1-sx end + if gy >= 0 then sy = 1-sy end + if gz >= 0 then sz = 1-sz end + + -- restricted x/y/z + local rx,ry,rz + rx = nil + ry = nil + rz = nil + + -- TODO: unset these when another boundary is crossed + + local i + local iend = ( + math.abs(tcx-cx) + + math.abs(tcy-cy) + + math.abs(tcz-cz) + ) + + for i=1,iend do + -- get the time it takes to hit the boundary + local tx = sx/depsilon(dx) + local ty = sy/depsilon(dy) + local tz = sz/depsilon(dz) + + local t, d, ck + + if tx < ty and tx < tz then + -- X first + d = 0 + t = tx + elseif ty < tx and ty < tz then + -- Y first + d = 1 + t = ty + else + -- Z first + d = 2 + t = tz + end + + sx = sx - t*dx + sy = sy - t*dy + sz = sz - t*dz + x1 = rx or x1 + t*dx*gx + y1 = ry or y1 + t*dy*gy + z1 = rz or z1 + t*dz*gz + + if d == 0 then + -- X first + sx = 1.0 + ck = rx or box_is_clear(cx+gx,y1+by1,z1+bz1,cx+gx,y1+by2,z1+bz2,canwrap) + if not ck then rx = cx + tlx end + if not rx then cx = cx + gx end + elseif d == 1 then + -- Y first + sy = 1.0 + ck = ry or box_is_clear(x1+bx1,cy+gy,z1+bz1,x1+bx2,cy+gy,z1+bz2,canwrap) + if not ck then ry = cy + tly end + if not ry then cy = cy + gy end + else + -- Z first + sz = 1.0 + ck = rz or box_is_clear(x1+bx1,y1+by1,cz+gz,x1+bx2,y1+by2,cz+gz,canwrap) + if not ck then rz = cz + tlz end + if not rz then cz = cz + gz end + end + + --if not ck then return x1-bx1, y1-by1, z1-bz1 end + end + -- + if rx then rx = rx - fx end + if ry then ry = ry - fy end + if rz then rz = rz - fz end + + return rx or x2, ry or y2, rz or z2 +end + +function isect_line_sphere(x1,y1,z1,fx,fy,fz,x2,y2,z2) + +end + diff --git a/pkg/base/obj_player.lua b/pkg/base/obj_player.lua index 9d8a218..c999df5 100644 --- a/pkg/base/obj_player.lua +++ b/pkg/base/obj_player.lua @@ -733,7 +733,7 @@ function new_player(settings) if this.tool == TOOL_BLOCK and this.blx1 then if (not this.t_newblock) and this.blocks > 0 then if this.blx1 >= 0 and this.blx1 < xlen and this.blz1 >= 0 and this.blz1 < zlen then - if this.bly1 <= ylen-3 then + if this.bly1 <= ylen-3 and map_is_buildable(this.blx1, this.bly1, this.blz1) then common.net_send(nil, common.net_pack("BHHHBBBB", 0x08, this.blx1, this.bly1, this.blz1, @@ -1037,8 +1037,9 @@ function new_player(settings) td, this.blx1, this.bly1, this.blz1, this.blx2, this.bly2, this.blz2 - = trace_map_ray_dist(camx,camy,camz, fwx,fwy,fwz, 5) - + = trace_map_ray_dist(camx,camy,camz, fwx,fwy,fwz, 5, false) + + this.bld1 = td this.bld2 = td @@ -1814,24 +1815,32 @@ function new_player(settings) -- TODO: wireframe cube if this.tool == TOOL_BLOCK and this.blx1 and (this.alive or this.respawning) then - bname, mdl_data = client.model_bone_get(mdl_cube, mdl_cube_bone) - - mdl_data_backup = mdl_data - - for i=1,#mdl_data do - if mdl_data[i].r > 4 then - mdl_data[i].r = math.max(this.blk_color[1], 5) --going all the way down to - mdl_data[i].g = math.max(this.blk_color[2], 5) --to 4 breaks it and you'd - mdl_data[i].b = math.max(this.blk_color[3], 5) --have to reload the model + if map_is_buildable(this.blx1, this.bly1, this.blz1) or MODE_BLOCK_PLACE_IN_AIR then + bname, mdl_data = client.model_bone_get(mdl_cube, mdl_cube_bone) + + mdl_data_backup = mdl_data + + for i=1,#mdl_data do + if mdl_data[i].r > 4 then + mdl_data[i].r = math.max(this.blk_color[1], 5) --going all the way down to + mdl_data[i].g = math.max(this.blk_color[2], 5) --to 4 breaks it and you'd + mdl_data[i].b = math.max(this.blk_color[3], 5) --have to reload the model + end end + + client.model_bone_set(mdl_cube, mdl_cube_bone, bname, mdl_data) + + client.model_render_bone_global(mdl_cube, mdl_cube_bone, + this.blx1+0.5, this.bly1+0.5, this.blz1+0.5, + 0.0, 0.0, 0.0, 24.0) --no rotation, 24 roughly equals the cube size + + else + client.model_render_bone_global(mdl_Xcube, mdl_Xcube_bone, + this.blx1+0.5, this.bly1+0.5, this.blz1+0.5, + 0.0, 0.0, 0.0, 24.0) + print(this.blx1.." "..this.bly1.." "..this.blz1) end - - client.model_bone_set(mdl_cube, mdl_cube_bone, bname, mdl_data) - - client.model_render_bone_global(mdl_cube, mdl_cube_bone, - this.blx1+0.5, this.bly1+0.5, this.blz1+0.5, - 0.0, 0.0, 0.0, 24.0) --no rotation, 24 roughly equals the cube size - elseif this.tool == TOOL_SPADE and this.blx1 and (this.alive or this.respawning) then + elseif this.tool == TOOL_SPADE and this.blx1 and (this.alive or this.respawning) and map_block_get(this.blx2, this.bly2, this.blz2) then client.model_render_bone_global(mdl_test, mdl_test_bone, this.blx1+0.5, this.bly1+0.5, this.blz1+0.5, rotpos*0.01, rotpos*0.004, 0.0, 0.1+0.01*math.sin(rotpos*0.071)) diff --git a/pkg/base/pmf/Xcube.pmf b/pkg/base/pmf/Xcube.pmf new file mode 100644 index 0000000..07a82e0 Binary files /dev/null and b/pkg/base/pmf/Xcube.pmf differ diff --git a/tools/Xcube.kv6 b/tools/Xcube.kv6 new file mode 100644 index 0000000..de6f4c0 Binary files /dev/null and b/tools/Xcube.kv6 differ diff --git a/tools/kv62pmf_Xcube_convert_win.bat b/tools/kv62pmf_Xcube_convert_win.bat new file mode 100644 index 0000000..61bd47b --- /dev/null +++ b/tools/kv62pmf_Xcube_convert_win.bat @@ -0,0 +1 @@ +kv62pmf.py Xcube.kv6 Xcube.pmf 1 1 bnXcube \ No newline at end of file