886 lines
24 KiB
Lua
886 lines
24 KiB
Lua
--[[
|
|
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 <http://www.gnu.org/licenses/>.
|
|
]]
|
|
|
|
print("pkg/base/client_start.lua starting")
|
|
print(...)
|
|
|
|
map_fname = nil
|
|
|
|
-- yeah this really should happen ASAP so we can boot people who suck
|
|
dofile("pkg/base/lib_util.lua")
|
|
|
|
--dofile("pkg/base/serpent.lua") -- serpent.block is a great debugging aid
|
|
|
|
local loose, user_toggles, user_settings = parse_commandline_options({...})
|
|
local user_config_filename = user_settings['user'] or "clsave/pub/user.json"
|
|
local controls_config_filename = user_settings['controls'] or "clsave/pub/controls.json"
|
|
-- FIXME: we don't expose documentation for valid user settings anywhere
|
|
|
|
user_config = common.json_load(user_config_filename)
|
|
if MODE_NUB_KICKONJOIN and user_config.kick_on_join then
|
|
error([[
|
|
Edit your clsave/pub/user.json file, and set kick_on_join to false.]])
|
|
end
|
|
print("json done!")
|
|
print("name:", user_config.name)
|
|
print("bio desc:", user_config.bio and user_config.bio.description)
|
|
|
|
-- OK, *NOW* we can load stuff.
|
|
dofile("pkg/base/common.lua")
|
|
|
|
tracers = {head = 1, tail = 0, time = 0}
|
|
|
|
client_tick_accum = 0.
|
|
|
|
map_fname = "*MAP"
|
|
|
|
if common.version.num < 5 then
|
|
error("Your version is too old! Please upgrade to 0.0-5 at least!")
|
|
end
|
|
if common.version.num >= 19 and common.version.num <= 21 then
|
|
error("0.0-19 through 0.0-21 have an incomplete OpenGL renderer. Due to the potential abuse, these versions are not allowed. Please upgrade to 0.0-22 at the least!")
|
|
end
|
|
|
|
-- define keys
|
|
controls_config = common.json_load(controls_config_filename) or {}
|
|
BTSK_FORWARD = controls_config.forward or SDLK_w
|
|
BTSK_BACK = controls_config.back or SDLK_s
|
|
BTSK_LEFT = controls_config.left or SDLK_a
|
|
BTSK_RIGHT = controls_config.right or SDLK_d
|
|
BTSK_JUMP = controls_config.jump or SDLK_SPACE
|
|
BTSK_CROUCH = controls_config.crouch or SDLK_LCTRL
|
|
BTSK_SNEAK = controls_config.sneak or SDLK_v
|
|
BTSK_RELOAD = controls_config.reload or SDLK_r
|
|
|
|
BTSK_TOOL1 = controls_config.tool1 or SDLK_1
|
|
BTSK_TOOL2 = controls_config.tool2 or SDLK_2
|
|
BTSK_TOOL3 = controls_config.tool3 or SDLK_3
|
|
BTSK_TOOL4 = controls_config.tool4 or SDLK_4
|
|
BTSK_TOOL5 = controls_config.tool5 or SDLK_5
|
|
BTSK_TOOLLAST = controls_config.toollast or SDLK_q
|
|
|
|
BTSK_COLORLEFT = controls_config.colorleft or SDLK_LEFT
|
|
BTSK_COLORRIGHT = controls_config.colorright or SDLK_RIGHT
|
|
BTSK_COLORUP = controls_config.colorup or SDLK_UP
|
|
BTSK_COLORDOWN = controls_config.colordown or SDLK_DOWN
|
|
|
|
BTSK_CHAT = controls_config.chat or SDLK_t
|
|
BTSK_COMMAND = SDLK_SLASH
|
|
BTSK_TEAMCHAT = controls_config.teamchat or SDLK_y
|
|
BTSK_SQUADCHAT = controls_config.squadchat or SDLK_u
|
|
BTSK_SCORES = controls_config.scores or SDLK_TAB
|
|
|
|
BTSK_QUIT = controls_config.quit or SDLK_ESCAPE
|
|
BTSK_YES = SDLK_y
|
|
BTSK_NO = SDLK_n
|
|
|
|
BTSK_DEBUG = SDLK_F1
|
|
BTSK_MAP = controls_config.map or SDLK_m
|
|
|
|
BTSK_TEAM = controls_config.team or SDLK_COMMA
|
|
BTSK_WPN = controls_config.wpn or SDLK_PERIOD
|
|
|
|
--[[ For user messages and hooking up GUI elements, we have a need for mapping
|
|
the key variables to names and back. We also need to seperate the internal
|
|
names with the natural-language descriptions. (Someday desc could be localized.)
|
|
]]
|
|
|
|
button_map = {
|
|
|
|
forward={key=BTSK_FORWARD,desc="Forward"},
|
|
back={key=BTSK_BACK,desc="Back"},
|
|
left={key=BTSK_LEFT,desc="Left"},
|
|
right={key=BTSK_RIGHT,desc="Right"},
|
|
jump={key=BTSK_JUMP,desc="Jump"},
|
|
crouch={key=BTSK_CROUCH,desc="Crouch"},
|
|
sneak={key=BTSK_SNEAK,desc="Sneak"},
|
|
reload={key=BTSK_RELOAD,desc="Reload"},
|
|
|
|
tool1={key=BTSK_TOOL1,desc="Tool 1"},
|
|
tool2={key=BTSK_TOOL2,desc="Tool 2"},
|
|
tool3={key=BTSK_TOOL3,desc="Tool 3"},
|
|
tool4={key=BTSK_TOOL4,desc="Tool 4"},
|
|
tool5={key=BTSK_TOOL5,desc="Tool 5"},
|
|
|
|
color_left={key=BTSK_COLORLEFT,desc="Color Left"},
|
|
color_right={key=BTSK_COLORRIGHT,desc="Color Right"},
|
|
color_up={key=BTSK_COLORUP,desc="Color Up"},
|
|
color_down={key=BTSK_COLORDOWN,desc="Color Down"},
|
|
|
|
chat={key=BTSK_CHAT,desc="Chat"},
|
|
command={key=BTSK_COMMAND,desc="Command"},
|
|
teamchat={key=BTSK_TEAMCHAT,desc="Team Chat"},
|
|
scores={key=BTSK_SCORES,desc="Scoreboard"},
|
|
|
|
quit={key=BTSK_QUIT,desc="Quit"},
|
|
yes={key=BTSK_YES,desc="Yes"},
|
|
no={key=BTSK_NO,desc="No"},
|
|
|
|
debug={key=BTSK_DEBUG,desc="Debug"},
|
|
map={key=BTSK_MAP,desc="Map"},
|
|
team={key=BTSK_TEAM,desc="Change Team"},
|
|
wpn={key=BTSK_WPN,desc="Change Weapon"},
|
|
}
|
|
|
|
-- equivalent - find a button from a keybinding
|
|
key_map = {}
|
|
for k, v in pairs(button_map) do
|
|
key_map[v.key] = {name=k, desc=v.desc}
|
|
end
|
|
|
|
-- map keysyms to their unicode values to fix keyup being an idiot
|
|
keys = {}
|
|
|
|
-- a list of arbitrary data with a "camera" that can render sublists.
|
|
function scroll_list(data, cam_start, cam_height)
|
|
|
|
local this = {list={},cam={
|
|
start=cam_start or 1,
|
|
height=cam_height-1 or 0}}
|
|
|
|
-- return a subset of the list table based on the camera position and height
|
|
function this.render(cam)
|
|
cam = cam or this.cam
|
|
local result = {}
|
|
local i
|
|
for i=cam.start, cam.start+cam.height do
|
|
table.insert(result, this.list[i])
|
|
end
|
|
return result
|
|
end
|
|
|
|
return this
|
|
end
|
|
|
|
chat_killfeed = scroll_list({}, 0, 10)
|
|
chat_text = scroll_list({}, 0, 6)
|
|
|
|
NET_MOVE_DELAY = 0.5
|
|
NET_ORIENT_DELAY = 0.1
|
|
t_net_move = nil
|
|
t_net_orient = nil
|
|
|
|
function tracer_add(x,y,z,ya,xa,time)
|
|
x = x or 0
|
|
y = y or 0
|
|
z = z or 0
|
|
local tc = {
|
|
x=x,y=y,z=z,
|
|
ya=ya,xa=xa,
|
|
time=time or tracers.time,
|
|
chn=client.wav_play_global(wav_whoosh,x,y,z,4.0)
|
|
}
|
|
|
|
tracers.tail = tracers.tail + 1
|
|
tracers[tracers.tail] = tc
|
|
end
|
|
|
|
function tracer_prune(time)
|
|
while tracers.head <= tracers.tail and tracers[tracers.head].time >= time + 0.4 do
|
|
tracers[tracers.head] = nil
|
|
tracers.head = tracers.head + 1
|
|
end
|
|
|
|
if tracers.head > tracers.tail then
|
|
tracers.head = 1
|
|
tracers.tail = 0
|
|
end
|
|
|
|
tracers.time = time
|
|
end
|
|
|
|
function chat_add(scrollist, mtime, msg, color)
|
|
table.insert(scrollist.list, #scrollist.list+1, {
|
|
mtime = mtime,
|
|
color = color,
|
|
msg = msg,
|
|
})
|
|
table.sort(scrollist.list, function(a, b) return a.mtime < b.mtime end)
|
|
end
|
|
|
|
function chat_prune(scrollist, mtime)
|
|
-- prune lines over the stored limit
|
|
-- prune lines that are old
|
|
while #scrollist.list > 0 and
|
|
(scrollist.list[1].mtime <= mtime - MODE_CHAT_LINGER or
|
|
#scrollist.list > MODE_CHAT_MAX) do
|
|
table.remove(scrollist.list, 1)
|
|
end
|
|
|
|
scrollist.cam.start = #scrollist.list - scrollist.cam.height
|
|
end
|
|
|
|
-- create map sprites
|
|
log_mspr = {}
|
|
|
|
mspr_player = {
|
|
-1,-3, 0,-3, 1,-3,
|
|
|
|
-2,-2, 2,-2,
|
|
|
|
-3,-1, 3,-1,
|
|
|
|
-3, 0, 3, 0,
|
|
|
|
-3, 1, 3, 1,
|
|
|
|
-2, 2, 2, 2,
|
|
|
|
-1, 3, 0, 3, 1, 3,
|
|
}
|
|
|
|
-- TODO: confirm the correct size of the intel + tent icons
|
|
mspr_intel = {
|
|
-3,-3, -2,-3, -1,-3, 0,-3, 1,-3, 2,-3, 3,-3,
|
|
|
|
-3,-2, 3,-2,
|
|
|
|
-3,-1, 3,-1,
|
|
|
|
-3, 0, 3, 0,
|
|
|
|
-3, 1, 3, 1,
|
|
|
|
-3, 2, 3, 2,
|
|
|
|
-3, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3,
|
|
}
|
|
|
|
mspr_tent = {
|
|
0,-3,
|
|
|
|
0,-2,
|
|
|
|
0,-1,
|
|
|
|
-3, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 3, 0,
|
|
|
|
0, 1,
|
|
|
|
0, 2,
|
|
|
|
0, 3,
|
|
}
|
|
|
|
-- TODO: up/down arrows
|
|
|
|
-- set stuff
|
|
rotpos = 0.0
|
|
sec_last = 0.
|
|
delta_last = 0.
|
|
debug_enabled = false
|
|
mouse_released = false
|
|
sensitivity = user_config.sensitivity or 1.0
|
|
sensitivity = sensitivity/1000.0
|
|
hold_to_zoom = user_config.hold_to_zoom or false
|
|
mouse_skip = 3
|
|
input_events = {}
|
|
|
|
gui_focus = nil
|
|
window_activated = true
|
|
|
|
show_scores = false
|
|
|
|
-- load images
|
|
img_crosshair = client.img_load("pkg/base/gfx/crosshair.tga")
|
|
img_crosshairhit = client.img_load("pkg/base/gfx/crosshairhit.tga")
|
|
img_chevron = client.img_load("pkg/base/gfx/chevron.tga")
|
|
|
|
-- load/make models
|
|
mdl_test = skin_load("pmf", "test.pmf", DIR_PKG_PMF)
|
|
mdl_test_bone = client.model_bone_find(mdl_test, "test")
|
|
mdl_cube = skin_load("pmf", "cube.pmf", DIR_PKG_PMF)
|
|
mdl_cube_bone = client.model_bone_find(mdl_cube, "bncube")
|
|
mdl_Xcube = skin_load("pmf", "Xcube.pmf", DIR_PKG_PMF)
|
|
mdl_Xcube_bone = client.model_bone_find(mdl_cube, "bnXcube")
|
|
mdl_spade, mdl_spade_bone = skin_load("pmf", "spade.pmf", DIR_PKG_PMF), 0
|
|
mdl_block, mdl_block_bone = skin_load("pmf", "block.pmf", DIR_PKG_PMF), 0
|
|
mdl_piano, mdl_piano_bone = skin_load("pmf", "piano.pmf", DIR_PKG_PMF), 0
|
|
|
|
mdl_tracer, mdl_tracer_bone = skin_load("pmf", "tracer.pmf", DIR_PKG_PMF), 0
|
|
|
|
-- quick hack to stitch a player model together
|
|
if false then
|
|
local head,body,arm,leg
|
|
head = skin_load("pmf", "src/playerhead.pmf", DIR_PKG_PMF)
|
|
body = skin_load("pmf", "src/playerbody.pmf", DIR_PKG_PMF)
|
|
arm = skin_load("pmf", "src/playerarm.pmf", DIR_PKG_PMF)
|
|
leg = skin_load("pmf", "src/playerleg.pmf", DIR_PKG_PMF)
|
|
|
|
local mname, mdata, mbone
|
|
local mbase = client.model_new(6)
|
|
mname, mdata = client.model_bone_get(head, 0)
|
|
mbase, mbone = client.model_bone_new(mbase)
|
|
client.model_bone_set(mbase, mbone, "head", mdata)
|
|
mname, mdata = client.model_bone_get(body, 0)
|
|
mbase, mbone = client.model_bone_new(mbase)
|
|
client.model_bone_set(mbase, mbone, "body", mdata)
|
|
mname, mdata = client.model_bone_get(arm, 0)
|
|
mbase, mbone = client.model_bone_new(mbase)
|
|
client.model_bone_set(mbase, mbone, "arm", mdata)
|
|
mname, mdata = client.model_bone_get(leg, 0)
|
|
mbase, mbone = client.model_bone_new(mbase)
|
|
client.model_bone_set(mbase, mbone, "leg", mdata)
|
|
|
|
client.model_save_pmf(mbase, "clsave/vol/player.pmf")
|
|
end
|
|
|
|
local _
|
|
_, mdl_block_data = client.model_bone_get(mdl_block, mdl_block_bone)
|
|
|
|
|
|
mdl_bbox = client.model_new(1)
|
|
mdl_bbox_bone_data1 = {
|
|
{radius=10, x = -100, y = -70, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = -70, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = -70, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = -70, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = 600, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = 600, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = 600, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = 600, z = 100, r = 255, g = 85, b = 85},
|
|
}
|
|
mdl_bbox_bone_data2 = {
|
|
{radius=10, x = -100, y = -70, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = -70, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = -70, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = -70, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = 410, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = 410, z = -100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = -100, y = 410, z = 100, r = 255, g = 85, b = 85},
|
|
{radius=10, x = 100, y = 410, z = 100, r = 255, g = 85, b = 85},
|
|
}
|
|
mdl_bbox, mdl_bbox_bone1 = client.model_bone_new(mdl_bbox)
|
|
mdl_bbox, mdl_bbox_bone2 = client.model_bone_new(mdl_bbox)
|
|
client.model_bone_set(mdl_bbox, mdl_bbox_bone1, "bbox_stand", mdl_bbox_bone_data1)
|
|
client.model_bone_set(mdl_bbox, mdl_bbox_bone2, "bbox_crouch", mdl_bbox_bone_data2)
|
|
|
|
|
|
-- set hooks
|
|
lflush = nil
|
|
function h_tick_main(sec_current, sec_delta)
|
|
if (not lflush) or sec_current < lflush - 0.8 then
|
|
lflush = sec_current
|
|
end
|
|
if sec_current >= lflush then
|
|
net_send_flush()
|
|
lflush = lflush + NET_FLUSH_C2S
|
|
if sec_current <= lflush then
|
|
lflush = sec_current
|
|
end
|
|
end
|
|
--FIXME: why is this POS prototyping variable still here, it is being used to control the player model's leg swing >:(
|
|
rotpos = rotpos + sec_delta*120.0
|
|
|
|
chat_prune(chat_text, sec_current)
|
|
chat_prune(chat_killfeed, sec_current)
|
|
|
|
local pkt, sockfd
|
|
while true do
|
|
pkt, sockfd = common.net_recv()
|
|
if not pkt then break end
|
|
|
|
local cid
|
|
cid, pkt = common.net_unpack("B", pkt)
|
|
--print("pkt", cid)
|
|
|
|
local hdl = network.sys_tab_handlers[cid]
|
|
if hdl then
|
|
hdl.f(sockfd, cli, plr, sec_current, common.net_unpack(hdl.s, pkt))
|
|
else
|
|
print(string.format("C: unhandled packet %02X", cid))
|
|
end
|
|
end
|
|
tracer_prune(sec_current)
|
|
bhealth_prune(sec_current)
|
|
|
|
local tickrate = 1/60.
|
|
local lowest_fps = 15
|
|
local max_ticksize = 1/lowest_fps
|
|
|
|
if sec_delta > max_ticksize then sec_delta = max_ticksize end
|
|
|
|
local moment = sec_current - sec_delta
|
|
client_tick_accum = client_tick_accum + sec_delta
|
|
|
|
for i=1,players.max do
|
|
local plr = players[i]
|
|
if plr then
|
|
plr.tick_listeners(sec_current, sec_delta)
|
|
end
|
|
end
|
|
|
|
while client_tick_accum > tickrate do
|
|
moment = moment + tickrate
|
|
local i
|
|
for i=1,players.max do
|
|
local plr = players[i]
|
|
if plr then
|
|
plr.tick(moment, tickrate)
|
|
end
|
|
end
|
|
for i=nades.head,nades.tail do
|
|
if nades[i] then nades[i].tick(moment, tickrate) end
|
|
end
|
|
for i=particles.head,particles.tail do
|
|
if particles[i] then particles[i].tick(moment, tickrate) end
|
|
end
|
|
nade_prune(sec_current)
|
|
particles_prune(sec_current)
|
|
|
|
for i=1,#intent do
|
|
intent[i].tick(moment, tickrate)
|
|
end
|
|
client_tick_accum = client_tick_accum - tickrate
|
|
end
|
|
|
|
if players.current and players[players.current] then
|
|
local plr = players[players.current]
|
|
|
|
if t_net_move and sec_current >= t_net_move then t_net_move = nil end
|
|
if t_net_orient and sec_current >= t_net_orient then t_net_orient = nil end
|
|
if not t_net_move then
|
|
t_net_move = sec_current + NET_MOVE_DELAY
|
|
local x,y,z
|
|
x,y,z = plr.get_pos()
|
|
x = x * 32.0
|
|
y = y * 32.0
|
|
z = z * 32.0
|
|
net_send(nil, common.net_pack("BBhhh"
|
|
, PKT_PLR_POS, 0x00, x, y, z))
|
|
end
|
|
if not t_net_orient then
|
|
t_net_orient = sec_current + NET_ORIENT_DELAY
|
|
local ya,xa,keys
|
|
ya,xa,keys = plr.get_orient()
|
|
ya = ya*128/math.pi
|
|
xa = xa*256/math.pi
|
|
|
|
net_send(nil, common.net_pack("BBbbB"
|
|
, PKT_PLR_ORIENT, 0x00, ya, xa, keys))
|
|
end
|
|
|
|
plr.camera_firstperson(sec_current, sec_delta)
|
|
else
|
|
-- TODO: idle camera
|
|
end
|
|
|
|
input_events = {}
|
|
|
|
sec_last = sec_current
|
|
delta_last = sec_delta
|
|
|
|
-- wait a bit
|
|
return 0.005
|
|
end
|
|
|
|
function h_tick_init(sec_current, sec_delta)
|
|
local i
|
|
--[[local squads = {[0]={},[1]={}}
|
|
for i=1,4 do
|
|
squads[0][i] = name_generate()
|
|
squads[1][i] = name_generate()
|
|
end]]
|
|
|
|
players.current = nil
|
|
|
|
--[[
|
|
for i=1,players.max do
|
|
players[i] = new_player({
|
|
name = (players.current == i and user_config.name) or name_generate(),
|
|
--[=[squad = squads[(i-1) % 2][
|
|
(math.floor((i-1)/2) % 4)+1],]=]
|
|
squad = nil,
|
|
team = (i-1) % 2, -- 0 == blue, 1 == green
|
|
weapon = WPN_RIFLE,
|
|
})
|
|
end
|
|
]]
|
|
|
|
intent[#intent+1] = new_intel({team = 0, iid = #intent+1})
|
|
intent[#intent+1] = new_tent({team = 0, iid = #intent+1})
|
|
intent[#intent+1] = new_intel({team = 1, iid = #intent+1})
|
|
intent[#intent+1] = new_tent({team = 1, iid = #intent+1})
|
|
|
|
--[[
|
|
chat_add(chat_text, sec_current, "Just testing the chat...", 0xFFFFFFFF)
|
|
chat_add(chat_text, sec_current, "BLUE MASTER RACE", 0xFF0000FF)
|
|
chat_add(chat_text, sec_current, "GREEN MASTER RACE", 0xFF00C000)
|
|
chat_add(chat_text, sec_current, "SALLY MASTER RACE", 0xFFAA00FF)
|
|
chat_add(chat_text, sec_current, "YOU ALL SUCK", 0xFFC00000)
|
|
]]
|
|
chat_add(chat_text, sec_current, "Welcome to Iceball!", 0xFFFF00AA)
|
|
chat_add(chat_killfeed, sec_current, "If it's broken, fix it yourself.", 0xFFFF00AA)
|
|
|
|
mouse_released = false
|
|
client.mouse_lock_set(true)
|
|
client.mouse_visible_set(false)
|
|
|
|
net_send(nil, common.net_pack("Bbbz", PKT_PLR_OFFER, -1, WPN_RIFLE, user_config.name or ""))
|
|
|
|
client.hook_tick = h_tick_main
|
|
net_send_flush()
|
|
return client.hook_tick(sec_current, sec_delta)
|
|
end
|
|
|
|
local function push_keypress(key, state, modif, sym)
|
|
table.insert(input_events, {GE_KEY, {key=key,state=state,modif=modif}})
|
|
if key_map[sym] ~= nil then
|
|
table.insert(input_events, {GE_BUTTON, {key=sym,button=key_map[sym],state=state,modif=modif}})
|
|
end
|
|
end
|
|
|
|
local w, h = client.screen_get_dims()
|
|
stored_pointer = {x=w/4, y=h*3/4} -- default to around the lower-left, where the text box is
|
|
|
|
function enter_typing_state()
|
|
mouse_released = true
|
|
client.mouse_lock_set(false)
|
|
client.mouse_visible_set(true)
|
|
if client.mouse_warp ~= nil then
|
|
client.mouse_warp(stored_pointer.x, stored_pointer.y)
|
|
end
|
|
end
|
|
|
|
function discard_typing_state(widget)
|
|
gui_focus = nil
|
|
if widget.clear_keyrepeat then widget.clear_keyrepeat() end
|
|
mouse_released = false
|
|
client.mouse_lock_set(true)
|
|
client.mouse_visible_set(false)
|
|
if client.mouse_warp ~= nil then
|
|
stored_pointer.x = mouse_xy.x
|
|
stored_pointer.y = mouse_xy.y
|
|
local w, h = client.screen_get_dims()
|
|
client.mouse_warp(w/2, h/2)
|
|
mouse_skip = 2
|
|
end
|
|
end
|
|
|
|
function h_key(sym, state, modif, uni)
|
|
local key = sym
|
|
|
|
-- unicode disabled for now until stuff gets moved to GE_BUTTON, sorry guys --GM
|
|
uni = nil
|
|
|
|
if key <= 256 then
|
|
local tmp
|
|
if state then tmp = 1 else tmp = 0 end
|
|
|
|
--print("key = " .. key .. " | state = " .. tmp)
|
|
|
|
if uni and state then
|
|
keys[sym] = uni
|
|
key = uni
|
|
elseif uni and not state then
|
|
if keys[sym] then
|
|
key = keys[sym]
|
|
end
|
|
end
|
|
|
|
--print("key = " .. key .. " | state = " .. tmp)
|
|
end
|
|
|
|
push_keypress(key, state, modif, sym)
|
|
|
|
-- disconnected ai
|
|
|
|
if not players[players.current] then
|
|
if state and key == SDLK_ESCAPE then
|
|
client.hook_tick = nil
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
-- typing text
|
|
|
|
if gui_focus ~= nil then
|
|
mouse_released = true
|
|
client.mouse_lock_set(false)
|
|
client.mouse_visible_set(true)
|
|
gui_focus.on_key(key, state, modif)
|
|
return
|
|
end
|
|
|
|
if not window_activated then
|
|
mouse_released = true
|
|
client.mouse_lock_set(false)
|
|
client.mouse_visible_set(true)
|
|
return
|
|
end
|
|
|
|
-- player entity ai
|
|
|
|
local plr = players[players.current]
|
|
|
|
if plr then
|
|
mouse_released = false
|
|
client.mouse_lock_set(true)
|
|
client.mouse_visible_set(false)
|
|
return plr.on_key(key, state, modif)
|
|
end
|
|
end
|
|
|
|
local function push_mouse_button(button, state)
|
|
table.insert(input_events, {GE_MOUSE_BUTTON, {button=button,down=state}})
|
|
end
|
|
|
|
local function push_mouse(x, y, dx, dy)
|
|
table.insert(input_events, {GE_MOUSE, {x=x, y=y, dx=dx, dy=dy}})
|
|
end
|
|
|
|
-- a nice little tool for checking the mouse state
|
|
function mouse_prettyprint()
|
|
|
|
local function xyp(n)
|
|
local s = tostring(mouse_xy[n])
|
|
if #s == 1 then return n..s.." "
|
|
elseif #s == 2 then return n..s.." "
|
|
elseif #s == 3 then return n..s.." "
|
|
elseif #s == 4 then return n..s.." "
|
|
else return n..s end
|
|
end
|
|
|
|
local function pollp(n)
|
|
if mouse_poll[n] then return n..'X ' else return n..' ' end
|
|
end
|
|
|
|
return xyp('x')..xyp('y')..xyp('dx')..xyp('dy')..
|
|
" "..pollp(1)..pollp(2)..pollp(3)..pollp(4)..pollp(5)
|
|
end
|
|
|
|
mouse_poll = {false,false,false,false,false}
|
|
mouse_xy = {x=0,y=0,dx=0,dy=0}
|
|
|
|
function h_mouse_button(button, state)
|
|
|
|
if mouse_poll[button] ~= state then
|
|
mouse_poll[button] = state
|
|
push_mouse_button(button, state)
|
|
end
|
|
|
|
if mouse_released and gui_focus == nil then
|
|
mouse_released = false
|
|
client.mouse_lock_set(true)
|
|
client.mouse_visible_set(false)
|
|
return
|
|
end
|
|
|
|
-- player entity ai
|
|
-- FIXME: no reassignable mouse button controls?
|
|
|
|
local plr = players[players.current]
|
|
if plr and gui_focus == nil then
|
|
return plr.on_mouse_button(button, state)
|
|
end
|
|
end
|
|
|
|
function h_mouse_motion(x, y, dx, dy)
|
|
|
|
mouse_xy.x = x
|
|
mouse_xy.y = y
|
|
mouse_xy.dx = dx
|
|
mouse_xy.dy = dy
|
|
|
|
push_mouse(x, y, dx, dy)
|
|
|
|
-- player entity ai
|
|
|
|
if not players[players.current] then return end
|
|
if mouse_released then return end
|
|
if mouse_skip > 0 then
|
|
mouse_skip = mouse_skip - 1
|
|
return
|
|
end
|
|
|
|
local plr = players[players.current]
|
|
if plr and gui_focus == nil then
|
|
return plr.on_mouse_motion(x, y, dx, dy)
|
|
end
|
|
end
|
|
|
|
function h_window_activate(active)
|
|
window_activated = active
|
|
if active then
|
|
mouse_released = false
|
|
client.mouse_lock_set(true)
|
|
client.mouse_visible_set(false)
|
|
else
|
|
mouse_released = true
|
|
client.mouse_lock_set(false)
|
|
client.mouse_visible_set(true)
|
|
end
|
|
end
|
|
|
|
-- load map
|
|
map_loaded = common.map_load(map_fname, "auto")
|
|
common.map_set(map_loaded)
|
|
|
|
print(client.map_fog_get())
|
|
--client.map_fog_set(24,0,32,60)
|
|
foglvl = user_config.fog or MODE_DEFAULT_FOG
|
|
if MODE_MAX_FOG and foglvl > MODE_MAX_FOG then
|
|
foglvl = MODE_MAX_FOG
|
|
end
|
|
if MODE_FOG_GL_EXTEND and client.renderer == "gl" then
|
|
foglvl = foglvl * math.sqrt(2)
|
|
end
|
|
client.map_fog_set(192,238,255,foglvl)
|
|
print(client.map_fog_get())
|
|
|
|
-- create map overview
|
|
-- TODO: update image when map gets mutilated
|
|
do
|
|
local xlen, ylen, zlen
|
|
xlen, ylen, zlen = common.map_get_dims()
|
|
img_overview = common.img_new(xlen, zlen)
|
|
img_overview_grid = common.img_new(xlen, zlen)
|
|
img_overview_icons = common.img_new(xlen, zlen)
|
|
local x,z
|
|
|
|
for z=0,zlen-1 do
|
|
for x=0,xlen-1 do
|
|
local l = common.map_pillar_get(x,z)
|
|
local c = argb_split_to_merged(l[7],l[6],l[5])
|
|
common.img_pixel_set(img_overview, x, z, c)
|
|
end
|
|
end
|
|
|
|
for z=63,zlen-1,64 do
|
|
for x=0,xlen-1 do
|
|
common.img_pixel_set(img_overview_grid, x, z, 0xFFFFFFFF)
|
|
end
|
|
end
|
|
for z=0,zlen-1 do
|
|
for x=63,xlen-1,64 do
|
|
common.img_pixel_set(img_overview_grid, x, z, 0xFFFFFFFF)
|
|
end
|
|
end
|
|
|
|
for x=0,xlen-1 do
|
|
common.img_pixel_set(img_overview_grid, x, zlen-1, 0xFFFF0000)
|
|
end
|
|
for z=0,zlen-1 do
|
|
common.img_pixel_set(img_overview_grid, xlen-1, z, 0xFFFF0000)
|
|
end
|
|
end
|
|
|
|
-- create colour palette image
|
|
img_cpal = common.img_new(64,64)
|
|
img_cpal_rect = common.img_new(8,8)
|
|
do
|
|
local cx,cy,x,y
|
|
for cy=0,7 do
|
|
for cx=0,7 do
|
|
local r,g,b
|
|
r = cpalette[cy*8+cx+1][1]
|
|
g = cpalette[cy*8+cx+1][2]
|
|
b = cpalette[cy*8+cx+1][3]
|
|
local c = argb_split_to_merged(r,g,b)
|
|
|
|
for y=cy*8+1,cy*8+6 do
|
|
for x=cx*8+1,cx*8+6 do
|
|
common.img_pixel_set(img_cpal, x, y, c)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local i
|
|
for i=0,6 do
|
|
common.img_pixel_set(img_cpal_rect, i, 0, 0xFFFFFFFF)
|
|
common.img_pixel_set(img_cpal_rect, 7, i, 0xFFFFFFFF)
|
|
common.img_pixel_set(img_cpal_rect, 7-i, 7, 0xFFFFFFFF)
|
|
common.img_pixel_set(img_cpal_rect, 0, 7-i, 0xFFFFFFFF)
|
|
end
|
|
end
|
|
|
|
-- hooks in place!
|
|
function client.hook_render()
|
|
if players and players[players.current] then
|
|
players[players.current].show_hud()
|
|
end
|
|
|
|
local i
|
|
for i=tracers.head,tracers.tail do
|
|
local tc = tracers[i]
|
|
|
|
local x,y,z
|
|
x,y,z = tc.x, tc.y, tc.z
|
|
|
|
local sya = math.sin(tc.ya)
|
|
local cya = math.cos(tc.ya)
|
|
local sxa = math.sin(tc.xa)
|
|
local cxa = math.cos(tc.xa)
|
|
|
|
local d = tracers.time - tc.time
|
|
d = d + 0.005
|
|
d = d * 600.0
|
|
x = x + sya*cxa*d
|
|
y = y + sxa*d
|
|
z = z + cya*cxa*d
|
|
|
|
client.wav_chn_update(tracers.chn, x, y, z)
|
|
|
|
client.model_render_bone_global(mdl_tracer, mdl_tracer_bone,
|
|
x,y,z,
|
|
0.0, -tc.xa, tc.ya, 1)
|
|
end
|
|
|
|
for i=nades.head,nades.tail do
|
|
if nades[i] then nades[i].render() end
|
|
end
|
|
|
|
for i=particles.head,particles.tail do
|
|
if particles[i] then particles[i].render() end
|
|
end
|
|
|
|
end
|
|
|
|
client.hook_tick = h_tick_init
|
|
client.hook_key = h_key
|
|
client.hook_mouse_button = h_mouse_button
|
|
client.hook_mouse_motion = h_mouse_motion
|
|
client.hook_window_activate = h_window_activate
|
|
|
|
function client.hook_kick(reason)
|
|
print("Kicked - "..reason)
|
|
function client.hook_tick()
|
|
client.mouse_lock_set(false)
|
|
client.mouse_visible_set(true)
|
|
return 0.01
|
|
end
|
|
local old_render = client.hook_render
|
|
local new_render = nil
|
|
function new_render_fn(...)
|
|
client.hook_render = old_render
|
|
local ret = client.hook_render(...)
|
|
old_render = client.hook_render
|
|
client.hook_render = new_render
|
|
font_large.print(30, 30, 0xFFAA0000, "KICKED")
|
|
font_mini.print(30, 65, 0xFFAA0000, reason)
|
|
end
|
|
new_render = new_render_fn
|
|
client.hook_render = new_render
|
|
end
|
|
|
|
print("pkg/base/client_start.lua loaded.")
|
|
|
|
--dofile("pkg/base/plug_snow.lua")
|
|
--dofile("pkg/base/plug_pmfedit.lua")
|