bunch of arch reworking; scripts take arguments now; arms/legs dangle too
This commit is contained in:
parent
6d2ee44e0d
commit
cc0461a9ca
32
common.h
32
common.h
@ -18,6 +18,7 @@
|
||||
#define MODEL_BONE_MAX 256
|
||||
#define MODEL_POINT_MAX 4096
|
||||
#define PACKET_LEN_MAX 1280
|
||||
#define PATH_LEN_MAX 128
|
||||
|
||||
//define RENDER_FACE_COUNT 2
|
||||
|
||||
@ -171,6 +172,23 @@ struct packet
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PATH_INVALID_ENUM = 0, // don't use this!
|
||||
|
||||
PATH_CLSAVE_BASEDIR,
|
||||
PATH_CLSAVE_PUBLIC,
|
||||
PATH_SVSAVE_BASEDIR,
|
||||
PATH_SVSAVE_PUBLIC,
|
||||
PATH_PKG_BASEDIR,
|
||||
PATH_PKG,
|
||||
|
||||
PATH_ERROR_BADCHARS,
|
||||
PATH_ERROR_ACCDENIED,
|
||||
|
||||
PATH_ENUM_MAX
|
||||
};
|
||||
|
||||
// img.c
|
||||
void img_free(img_t *img);
|
||||
img_t *img_load_tga(const char *fname);
|
||||
@ -183,10 +201,16 @@ void icelua_deinit(void);
|
||||
|
||||
// main.c
|
||||
extern camera_t tcam;
|
||||
extern map_t *clmap;
|
||||
extern map_t *svmap;
|
||||
extern map_t *clmap, *svmap;
|
||||
extern SDL_Surface *screen;
|
||||
extern int force_redraw;
|
||||
|
||||
extern int boot_mode;
|
||||
|
||||
extern int main_argc;
|
||||
extern char **main_argv;
|
||||
extern int main_largstart;
|
||||
|
||||
int error_sdl(char *msg);
|
||||
int error_perror(char *msg);
|
||||
|
||||
@ -211,6 +235,10 @@ void net_packet_free(packet_t *pkt);
|
||||
int net_init(void);
|
||||
void net_deinit(void);
|
||||
|
||||
// path.c
|
||||
char *path_filter(const char *path);
|
||||
int path_get_type(const char *path);
|
||||
|
||||
// render.c
|
||||
#ifdef RENDER_FACE_COUNT
|
||||
extern int render_face_remain;
|
||||
|
@ -3,7 +3,7 @@
|
||||
Congratulations for successfully extracting Iceball from its archive!
|
||||
I'm assuming you did that, right?
|
||||
If you're running it from within the archive, extract the damn thing NOW.
|
||||
It won't work, otherwise.
|
||||
(It won't work otherwise.)
|
||||
|
||||
Anyhow, if this manual isn't clear enough, please inform us somehow!
|
||||
|
||||
@ -74,12 +74,41 @@ UNIX:
|
||||
|
||||
You should be fine from there.
|
||||
|
||||
NOTE: On Windows, you will need to check stderr.txt for the help you need.
|
||||
I haven't worked out how to make SDL *NOT* do this stupid crap yet.
|
||||
|
||||
By the way, here's a tip for the Windows users:
|
||||
Double-click opencmd.bat. It should get you into the right directory.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Iceball refers to one of two things:
|
||||
- The game engine.
|
||||
- The game itself, currently located in pkg/base.
|
||||
- The base game itself, currently located in pkg/base.
|
||||
|
||||
If you wish to screw with the base game, check docs/modding_101.txt.
|
||||
|
||||
It's advised that you don't screw with the engine, though,
|
||||
unless you wish to improve the mainline engine,
|
||||
in which case you should prod me (GreaseMonkey) on IRC,
|
||||
#AoS @ QuakeNet.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
TODO: more stuff
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
List of things NOT to request:
|
||||
- SMG.
|
||||
- SMG.
|
||||
- Family-friendly filtering of the name generator.
|
||||
- SMG.
|
||||
- Sprinting.
|
||||
- RPG.
|
||||
- Nerfing the rifle.
|
||||
- SMG.
|
||||
- Any weapons which have not been field-tested.
|
||||
- Any weapons which are SMG.
|
||||
- SMG.
|
||||
|
||||
|
58
docs/format_icemap.txt
Normal file
58
docs/format_icemap.txt
Normal file
@ -0,0 +1,58 @@
|
||||
basically, an extensible tagged format.
|
||||
|
||||
note:
|
||||
db means a byte
|
||||
dw means a word (2 bytes here)
|
||||
dd means a dword (4 bytes here)
|
||||
|
||||
for starters, there's a header,
|
||||
just in case some clutz decides to use this in AoS
|
||||
db "IceMap", 0x1A, 0x01
|
||||
|
||||
then a bunch of chunks follow in the format
|
||||
db "7 Chars", length
|
||||
|
||||
or, if the length is >= 255:
|
||||
db "7 Chars", 255
|
||||
dd length
|
||||
|
||||
the terminator is:
|
||||
db " ", 0
|
||||
yes, that's 7 spaces.
|
||||
|
||||
for AoS compatibility, the "header" CAN be at the end, BUT:
|
||||
- MapData is NOT to be defined.
|
||||
- all non-air blocks are assumed to be type 1.
|
||||
|
||||
now, here are the defined chunks as per version 1 of the format.
|
||||
MapData:
|
||||
db "MapData", 255
|
||||
dd map_length
|
||||
dw len_x, len_y, len_z
|
||||
; map data goes here
|
||||
|
||||
this contains the map itself.
|
||||
|
||||
must appear exactly ONCE,
|
||||
or not at all if using AoS compat.
|
||||
|
||||
MetaInf:
|
||||
db "MetaInf", length
|
||||
db field_name, 0
|
||||
db field_data, 0
|
||||
|
||||
this contains meta info pertaining to the map.
|
||||
|
||||
yes, there can be more than one MetaInf with the same name.
|
||||
|
||||
defined names are:
|
||||
"*Name": name of this map
|
||||
"*Author": who made this map
|
||||
"*Tool": program responsible for making this map
|
||||
|
||||
any custom names MUST NOT be prefixed with a *;
|
||||
this is reserved for OFFICIALLY DEFINED NAMES ONLY.
|
||||
|
||||
all tools MUST leave "*Tool" fields intact.
|
||||
|
||||
this field can appear many times.
|
@ -15,6 +15,8 @@ svsave/<group name>/<mod name>/*
|
||||
You can use a common name for these if you want,
|
||||
but please stick to your group name.
|
||||
|
||||
Also, "pub" is not a valid group name, as you will find out soon...
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
There are libraries in the base mod!
|
||||
@ -25,19 +27,27 @@ Use pkg/base/lib_*.lua for them.
|
||||
For security reasons,
|
||||
you are only allowed to modify files in these directories:
|
||||
Client only:
|
||||
clsave/<group name>/*
|
||||
clsave/<group name>/<mod name>/*
|
||||
Server only:
|
||||
svsave/<group name>/*
|
||||
svsave/<group name>/<mod name>/*
|
||||
|
||||
You can also modify them.
|
||||
|
||||
You ARE allowed to read these:
|
||||
pkg/*
|
||||
Client only:
|
||||
clsave/*
|
||||
clsave/pub/*
|
||||
Server only:
|
||||
svsave/*
|
||||
svsave/pub/*
|
||||
|
||||
(TODO: enforce this!)
|
||||
|
||||
Note, it is advised that you DO NOT run client-local Lua scripts!
|
||||
If you do, you open your mod up to an awful lot of cheating.
|
||||
|
||||
In fact, you should be very careful with ANYTHING in clsave.
|
||||
If it's anything other than a config, you will have to sanity-check it.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Aside from maps, don't rip stuff from Ace of Spades,
|
||||
@ -49,8 +59,23 @@ I would encourage you to use that for AoS data instead.
|
||||
If you're taking on this task, please do the following:
|
||||
- Include models/sounds from all versions where possible
|
||||
- Denote stuff by the first version that uses it in this format:
|
||||
pkg/<group name>/<pack name>/whatever/*
|
||||
-
|
||||
pkg/<group name>/<pack name>/whatever/name-X.XX.whatever
|
||||
For instance, shotgun.kv6 would be:
|
||||
pkg/<group name>/<pack name>/kv6/shotgun-0.58.kv6
|
||||
OR, if converted to PMF:
|
||||
pkg/<group name>/<pack name>/pmf/shotgun-0.58.pmf
|
||||
- I think that's it, really.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
A quick template for a mod that uses a custom set of PMFs:
|
||||
|
||||
-- main_client.lua
|
||||
PKG_DIR_PMF = common.pkg_base.."/pmf"
|
||||
loadfile("pkg/base/main_client.lua")(...)
|
||||
|
||||
-- main_server.lua
|
||||
loadfile("pkg/base/main_server.lua")(...)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
@ -61,6 +86,7 @@ Maps:
|
||||
- well, why *wouldn't* we support that?
|
||||
- Aiming to support a modified + headered map format, too.
|
||||
Y'know, smaller maps and whatnot.
|
||||
Will probably designate *.icemap, because who uses DOS these days.
|
||||
|
||||
Models:
|
||||
- *.pmf: Point Model Format, designed for this game
|
||||
|
@ -9,6 +9,12 @@ valid characters are listed here (ignoring the path separator):
|
||||
-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz
|
||||
anything else is invalid and will just be outright rejected
|
||||
|
||||
furthermore, no paths will be accepted where a . follows a /
|
||||
this means that hidden files on unixlikes will not be accepted!
|
||||
|
||||
files that are meant to be intercepted should be prefixed with a *
|
||||
e.g. "*thismap"
|
||||
|
||||
maximum path length is 128
|
||||
|
||||
stuff that's actually implemented will be marked with an @
|
||||
@ -41,6 +47,17 @@ client/server.hook_tick = fn(sec_curtime, sec_delta)->sec_wait @
|
||||
NOTE: DO NOT USE COMMON FOR THIS HOOK!
|
||||
(only client/server is accepted)
|
||||
|
||||
client/server.hook_file = fn(ftype, fname, clisock)->object
|
||||
sets a hook to intercept networked file requests
|
||||
|
||||
"clisock" is the socket pertaining to the file request
|
||||
|
||||
can return nil to cancel the request
|
||||
can return true to perform the default request
|
||||
|
||||
NOTE: DO NOT USE COMMON FOR THIS HOOK!
|
||||
(only client/server is accepted)
|
||||
|
||||
client.hook_render = fn() @
|
||||
sets a hook called every frame
|
||||
|
||||
@ -72,14 +89,12 @@ client.mouse_lock_set(state) @
|
||||
client.mouse_visible_set(state) @
|
||||
shows / hides the mouse depending on "state"
|
||||
|
||||
success = server.map_load(fname, fmt = "auto")
|
||||
map = common.map_load(fname, fmt = "auto")
|
||||
loads a map, either .vxl or some format we might invent
|
||||
which will probably be .vxl with our own header
|
||||
+ changed meaning for the 4th colour byte
|
||||
|
||||
this will also send the map to the other clients
|
||||
|
||||
common.map_new(lx, ly, lz)
|
||||
map = common.map_new(lx, ly, lz)
|
||||
creates a new map
|
||||
|
||||
note, ly is the *height* of the new map
|
||||
@ -89,7 +104,11 @@ common.map_new(lx, ly, lz)
|
||||
|
||||
this will throw a lua error if it fails.
|
||||
|
||||
common.map_save(fname, fmt = "bsm")
|
||||
common.map_set(map)
|
||||
sets the "current" map to "map"
|
||||
note, "map" can be nil to disable rendering anything
|
||||
|
||||
common.map_save(map, fname, fmt = "icemap")
|
||||
saves a map to a file
|
||||
|
||||
this will throw a lua error if it fails.
|
||||
@ -250,19 +269,19 @@ client.model_render_bone_local(pmf, boneidx, px, py, pz, ry, rx, ry2, scale) @
|
||||
width, height = client.screen_get_dims() @
|
||||
gets the dimensions of the screen
|
||||
|
||||
img, width, height = client.img_load(fname) @
|
||||
img, width, height = common.img_load(fname) @
|
||||
loads an image with filename "fname"
|
||||
remember to free it when you're done
|
||||
as this is only a light userdata
|
||||
|
||||
if this fails, img, width, height will all be nil
|
||||
|
||||
client.img_free(img) @
|
||||
common.img_free(img) @
|
||||
free the given image
|
||||
if you don't do this then it's memoryleaktopia
|
||||
(plus i'm allowed to kill you)
|
||||
|
||||
width, height = img_get_dims(img) @
|
||||
width, height = common.img_get_dims(img) @
|
||||
gets the image's dimensions
|
||||
|
||||
client.img_blit(img, dx, dy, width = iwidth, height = iheight, sx = 0, sy = 0, color = 0xFFFFFFFF) @
|
||||
|
@ -27,12 +27,12 @@ Base encapsulation:
|
||||
"flags" has these bits:
|
||||
bits 0-2:
|
||||
000 = * RESERVED *
|
||||
001 = user data [ NOT SUPPORTED YET ]
|
||||
001 = JSON data [ NOT SUPPORTED YET ]
|
||||
010 = lua script
|
||||
011 = map data
|
||||
100 = pmf model
|
||||
101 = tga image
|
||||
110 = * RESERVED *
|
||||
110 = CSV log data [ NOT SUPPORTED YET ]
|
||||
111 = * RESERVED *
|
||||
0x31 flags clen.u32 ulen.u32 namelen name[namelen] 0x00:
|
||||
Start file transfer
|
||||
@ -40,12 +40,12 @@ Base encapsulation:
|
||||
"flags" has these bits:
|
||||
bits 0-2:
|
||||
000 = * RESERVED *
|
||||
001 = user data [ NOT SUPPORTED YET ]
|
||||
001 = JSON data [ NOT SUPPORTED YET ]
|
||||
010 = lua script
|
||||
011 = map data
|
||||
100 = pmf model
|
||||
101 = tga image
|
||||
110 = * RESERVED *
|
||||
110 = CSV log data [ NOT SUPPORTED YET ]
|
||||
111 = * RESERVED *
|
||||
"clen" is the compressed length
|
||||
"ulen" is the uncompressed length
|
||||
@ -110,11 +110,19 @@ Iceball Base Mod:
|
||||
0x07 pid: (S->C)
|
||||
removes player from server
|
||||
|
||||
0x08:
|
||||
0x08 x.u16 y.u16 z.u16 b g r typ:
|
||||
place a block
|
||||
|
||||
0x09 x.u16 y.u16 z.u16:
|
||||
destroy a block
|
||||
|
||||
0x0A x.u16 y.u16 z.u16:
|
||||
destroy a 3 high pillar
|
||||
|
||||
0x05
|
||||
0x0B x.u16 y.u16 z.u16:
|
||||
collapse a section of blocks
|
||||
|
||||
0x05 pid: (S->C)
|
||||
NOTE: will be IGNORED if the floodfill hits the bottom!
|
||||
|
||||
0x0C pid x.fs y.fs z.fs ya.u8 xa.u8: (S->C)
|
||||
player spawn
|
||||
|
802
lua.c
802
lua.c
@ -51,755 +51,15 @@ int icelua_force_get_integer(lua_State *L, int table, char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "lua_camera.h"
|
||||
#include "lua_image.h"
|
||||
#include "lua_input.h"
|
||||
#include "lua_map.h"
|
||||
#include "lua_model.h"
|
||||
|
||||
// common functions
|
||||
int icelua_fn_common_map_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, just give off nils
|
||||
if(map == NULL)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
lua_pushinteger(L, map->xlen);
|
||||
lua_pushinteger(L, map->ylen);
|
||||
lua_pushinteger(L, map->zlen);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
int icelua_fn_common_map_pillar_get(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
int px, pz;
|
||||
int i;
|
||||
|
||||
px = lua_tointeger(L, 1);
|
||||
pz = lua_tointeger(L, 2);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, return nil
|
||||
if(map == NULL)
|
||||
return 0;
|
||||
|
||||
// get a pillar
|
||||
uint8_t *p = map->pillars[(pz&(map->zlen-1))*map->xlen+(px&(map->xlen-1))];
|
||||
|
||||
// build the list
|
||||
int llen = 4*((255&(int)*p)+1);
|
||||
lua_createtable(L, llen, 0);
|
||||
p += 4;
|
||||
|
||||
for(i = 1; i <= llen; i++)
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushinteger(L, *(p++));
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_map_pillar_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
int px, pz, tlen;
|
||||
int i;
|
||||
|
||||
px = lua_tointeger(L, 1);
|
||||
pz = lua_tointeger(L, 2);
|
||||
if(!lua_istable(L, 3))
|
||||
return luaL_error(L, "expected a table, got something else");
|
||||
tlen = lua_objlen(L, 3);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, ignore (for now)
|
||||
if(map == NULL)
|
||||
return 0;
|
||||
|
||||
// validate that the table is not TOO large and is 4-byte aligned wrt size
|
||||
if((tlen&3) || tlen > 1024)
|
||||
return luaL_error(L, "table length %d invalid", tlen);
|
||||
|
||||
// validate the table's input range
|
||||
for(i = 0; i < tlen; i++)
|
||||
{
|
||||
lua_pushinteger(L, 1+i);
|
||||
lua_gettable(L, 3);
|
||||
int v = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if(v < 0 || v > 255)
|
||||
return luaL_error(L, "value at index %d out of unsigned byte range (%d)"
|
||||
, 1+i, v);
|
||||
}
|
||||
|
||||
// validate the table data
|
||||
i = 0;
|
||||
for(;;)
|
||||
{
|
||||
lua_pushinteger(L, 1+i+0);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+1);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+2);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+3);
|
||||
lua_gettable(L, 3);
|
||||
int n = lua_tointeger(L, -4);
|
||||
int s = lua_tointeger(L, -3);
|
||||
int e = lua_tointeger(L, -2);
|
||||
int a = lua_tointeger(L, -1);
|
||||
lua_pop(L, 4);
|
||||
|
||||
//printf("%i %i | %i %i | %i %i %i %i\n",px,pz,i,tlen,n,s,e,a);
|
||||
|
||||
// Note, we are not supporting the shenanigans you can do in VOXLAP.
|
||||
// Especially considering that editing said shenanigans causes issues.
|
||||
// Also noting that said shenanigans weren't all that exploited,
|
||||
// VOXLAP automatically corrects shenanigans when you edit stuff,
|
||||
// and pyspades has no support for such shenanigans.
|
||||
if(e+1 < s)
|
||||
return luaL_error(L, "pillar has end+1 < start (%d < %d)"
|
||||
, e+1, s);
|
||||
if(i != 0 && s < a)
|
||||
return luaL_error(L, "pillar has start < air (%d < %d)"
|
||||
, s, a);
|
||||
if(n != 0 && n-1 < e-s+1)
|
||||
return luaL_error(L, "pillar has length < top length (%d < %d)"
|
||||
, n-1, e-s+1);
|
||||
|
||||
|
||||
// NOTE: this doesn't validate the BGRT (colour/type) entries.
|
||||
int la = 0;
|
||||
if(n == 0)
|
||||
{
|
||||
int exlen = (e-s+1)*4+i+4;
|
||||
if(exlen != tlen)
|
||||
return luaL_error(L, "pillar table len should be %d, got %d instead"
|
||||
, exlen, tlen);
|
||||
break;
|
||||
} else {
|
||||
i += 4*n;
|
||||
// should always be colour on the bottom!
|
||||
if(i > tlen-4)
|
||||
return luaL_error(L, "pillar table overflow when validating");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// expand the pillar data if necessary
|
||||
int idx = (pz&(map->zlen-1))*map->xlen+(px&(map->xlen-1));
|
||||
uint8_t *p = map->pillars[idx];
|
||||
if((p[0]+1)*4 < tlen)
|
||||
{
|
||||
p = map->pillars[idx] = realloc(p, tlen+4);
|
||||
p[0] = (tlen>>2)-1;
|
||||
}
|
||||
|
||||
// transfer the table data
|
||||
p += 4;
|
||||
for(i = 1; i <= tlen; i++)
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
lua_gettable(L, 3);
|
||||
*(p++) = (uint8_t)lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
force_redraw = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_new(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 1);
|
||||
int bonemax = 5;
|
||||
|
||||
if(top >= 1)
|
||||
bonemax = lua_tointeger(L, 1);
|
||||
if(bonemax < 0 || bonemax >= MODEL_BONE_MAX)
|
||||
return luaL_error(L, "cannot have %d bones, max is %d", bonemax, MODEL_BONE_MAX);
|
||||
|
||||
model_t *pmf = model_new(bonemax);
|
||||
|
||||
// TODO: add this to a clean-up linked list or something
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_load_pmf(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
const char *fname = lua_tostring(L, 1);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
model_t *pmf = model_load_pmf(fname);
|
||||
|
||||
// TODO: add this to a clean-up linked list or something
|
||||
if(pmf == NULL)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_save_pmf(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
const char *fname = lua_tostring(L, 2);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
lua_pushboolean(L, !model_save_pmf(pmf, fname));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
model_free(pmf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_len(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
lua_pushinteger(L, pmf->bonelen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_new(lua_State *L)
|
||||
{
|
||||
// TODO: check for size limit
|
||||
|
||||
int top = icelua_assert_stack(L, 1, 2);
|
||||
int ptmax = 20;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
if(top >= 2)
|
||||
ptmax = lua_tointeger(L, 2);
|
||||
if(ptmax < 0 || ptmax >= MODEL_POINT_MAX)
|
||||
return luaL_error(L, "cannot have %d points, max is %d", ptmax, MODEL_POINT_MAX);
|
||||
|
||||
// ensure there is room for this bone
|
||||
int tsize = pmf->bonelen+1;
|
||||
|
||||
if(pmf->bonelen >= pmf->bonemax)
|
||||
{
|
||||
int csize = (pmf->bonemax*3)/2+1;
|
||||
if(csize < tsize)
|
||||
csize = tsize;
|
||||
|
||||
pmf = model_extend(pmf, csize);
|
||||
}
|
||||
|
||||
// now add it
|
||||
model_bone_t *bone = model_bone_new(pmf, ptmax);
|
||||
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
lua_pushinteger(L, bone->parent_idx);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 2);
|
||||
int boneidx;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
|
||||
model_bone_free(pmf->bones[boneidx]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_get(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
// push args
|
||||
lua_pushstring(L, bone->name);
|
||||
lua_createtable(L, bone->ptlen, 0);
|
||||
|
||||
// fill the table
|
||||
for(i = 0; i < bone->ptlen; i++)
|
||||
{
|
||||
model_point_t *pt = &(bone->pts[i]);
|
||||
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_createtable(L, 0, 7);
|
||||
|
||||
lua_pushinteger(L, pt->radius);
|
||||
lua_setfield(L, -2, "radius");
|
||||
|
||||
lua_pushinteger(L, pt->x);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushinteger(L, pt->y);
|
||||
lua_setfield(L, -2, "y");
|
||||
lua_pushinteger(L, pt->z);
|
||||
lua_setfield(L, -2, "z");
|
||||
|
||||
lua_pushinteger(L, pt->r);
|
||||
lua_setfield(L, -2, "r");
|
||||
lua_pushinteger(L, pt->g);
|
||||
lua_setfield(L, -2, "g");
|
||||
lua_pushinteger(L, pt->b);
|
||||
lua_setfield(L, -2, "b");
|
||||
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_set(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 4, 4);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
const char *name = lua_tostring(L, 3);
|
||||
if(name == NULL)
|
||||
return luaL_error(L, "bone name cannot be nil");
|
||||
if(strlen(name) > 15)
|
||||
return luaL_error(L, "bone name too long, was %d chars, max is 15", strlen(name));
|
||||
|
||||
if(!lua_istable(L, 4))
|
||||
return luaL_error(L, "expected a table, got something else");
|
||||
|
||||
// check if the bone is large enough
|
||||
|
||||
int tsize = lua_objlen(L, 4);
|
||||
|
||||
if(tsize > bone->ptmax)
|
||||
{
|
||||
int csize = (bone->ptmax*3)/2+1;
|
||||
if(csize < tsize)
|
||||
csize = tsize;
|
||||
|
||||
//printf("bone extend %i %i %i\n", bone->ptmax, tsize, csize);
|
||||
bone = model_bone_extend(bone, csize);
|
||||
}
|
||||
|
||||
// set the bone's name
|
||||
strcpy(bone->name, name);
|
||||
|
||||
// load the table's contents
|
||||
bone->ptlen = 0;
|
||||
for(i = 0; i < tsize; i++)
|
||||
{
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_gettable(L, 4);
|
||||
|
||||
// note, bones will be rejected if:
|
||||
// - radius,x,y,z,r,g,b are missing
|
||||
int radius = icelua_force_get_integer(L, -1, "radius");
|
||||
int x = icelua_force_get_integer(L, -1, "x");
|
||||
int y = icelua_force_get_integer(L, -1, "y");
|
||||
int z = icelua_force_get_integer(L, -1, "z");
|
||||
int r = icelua_force_get_integer(L, -1, "r");
|
||||
int g = icelua_force_get_integer(L, -1, "g");
|
||||
int b = icelua_force_get_integer(L, -1, "b");
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
// - 0 <= radius < 65536 fails
|
||||
if(radius < 0 || radius >= 65536)
|
||||
return luaL_error(L, "radius out of range of 0 <= %d < 65536", radius);
|
||||
|
||||
// - -32768 <= x,y,z < 32768 fails
|
||||
if(x < -32768 || x >= 32768)
|
||||
return luaL_error(L, "x out of range of -32768 <= %d < 32768", x);
|
||||
if(y < -32768 || y >= 32768)
|
||||
return luaL_error(L, "y out of range of -32768 <= %d < 32768", x);
|
||||
if(z < -32768 || z >= 32768)
|
||||
return luaL_error(L, "z out of range of -32768 <= %d < 32768", x);
|
||||
|
||||
// - 0 <= r,g,b < 256 fails
|
||||
if(r < 0 || r >= 256)
|
||||
return luaL_error(L, "r out of range of 0 <= %d < 256", r);
|
||||
if(g < 0 || g >= 256)
|
||||
return luaL_error(L, "g out of range of 0 <= %d < 256", g);
|
||||
if(b < 0 || b >= 256)
|
||||
return luaL_error(L, "b out of range of 0 <= %d < 256", b);
|
||||
|
||||
// add it in!
|
||||
model_point_t *pt = &(bone->pts[i]);
|
||||
|
||||
pt->radius = radius;
|
||||
pt->x = x, pt->y = y, pt->z = z;
|
||||
pt->r = r, pt->g = g, pt->b = b;
|
||||
pt->resv1 = 0;
|
||||
|
||||
bone->ptlen++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_find(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
const char *name = lua_tostring(L, 2);
|
||||
if(name == NULL)
|
||||
return luaL_error(L, "name must be a string");
|
||||
|
||||
for(i = 0; i < pmf->bonemax; i++)
|
||||
{
|
||||
model_bone_t *bone = pmf->bones[i];
|
||||
|
||||
if(!strcmp(bone->name, name))
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_mouse_lock_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
SDL_WM_GrabInput(lua_toboolean(L, 1)
|
||||
? SDL_GRAB_ON
|
||||
: SDL_GRAB_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_mouse_visible_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
SDL_ShowCursor(lua_toboolean(L, 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_map_fog_get(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushinteger(L, (fog_color>>16)&255);
|
||||
lua_pushinteger(L, (fog_color>>8)&255);
|
||||
lua_pushinteger(L, (fog_color)&255);
|
||||
lua_pushnumber(L, fog_distance);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int icelua_fn_client_map_fog_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 4, 4);
|
||||
|
||||
int r = lua_tointeger(L, 1)&255;
|
||||
int g = lua_tointeger(L, 2)&255;
|
||||
int b = lua_tointeger(L, 3)&255;
|
||||
fog_distance = lua_tonumber(L, 4);
|
||||
if(fog_distance < 5.0f)
|
||||
fog_distance = 5.0f;
|
||||
if(fog_distance > FOG_MAX_DISTANCE)
|
||||
fog_distance = FOG_MAX_DISTANCE;
|
||||
|
||||
fog_color = (r<<16)|(g<<8)|b;
|
||||
force_redraw = 1;
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_point(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 5);
|
||||
float dx, dy, dz;
|
||||
float zoom = 1.0f, roll = 0.0f;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
if(top >= 4)
|
||||
zoom = lua_tonumber(L, 4);
|
||||
if(top >= 5)
|
||||
roll = lua_tonumber(L, 5);
|
||||
|
||||
//printf("%f\n", zoom);
|
||||
cam_point_dir(&tcam, dx, dy, dz, zoom, roll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_local(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float dx, dy, dz;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx += dx*tcam.mxx+dy*tcam.myx+dz*tcam.mzx;
|
||||
tcam.mpy += dx*tcam.mxy+dy*tcam.myy+dz*tcam.mzy;
|
||||
tcam.mpz += dx*tcam.mxz+dy*tcam.myz+dz*tcam.mzz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_global(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float dx, dy, dz;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx += dx;
|
||||
tcam.mpy += dy;
|
||||
tcam.mpz += dz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_to(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float px, py, pz;
|
||||
|
||||
px = lua_tonumber(L, 1);
|
||||
py = lua_tonumber(L, 2);
|
||||
pz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx = px;
|
||||
tcam.mpy = py;
|
||||
tcam.mpz = pz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_get_pos(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushnumber(L, tcam.mpx);
|
||||
lua_pushnumber(L, tcam.mpy);
|
||||
lua_pushnumber(L, tcam.mpz);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_get_forward(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushnumber(L, tcam.mzx);
|
||||
lua_pushnumber(L, tcam.mzy);
|
||||
lua_pushnumber(L, tcam.mzz);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_client_model_render_bone_global(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 9, 9);
|
||||
float px, py, pz;
|
||||
float ry, rx, ry2;
|
||||
float scale;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
px = lua_tonumber(L, 3);
|
||||
py = lua_tonumber(L, 4);
|
||||
pz = lua_tonumber(L, 5);
|
||||
|
||||
ry = lua_tonumber(L, 6);
|
||||
rx = lua_tonumber(L, 7);
|
||||
ry2 = lua_tonumber(L, 8);
|
||||
|
||||
scale = lua_tonumber(L, 9);
|
||||
|
||||
render_pmf_bone(screen->pixels, screen->w, screen->h, screen->pitch/4, &tcam,
|
||||
bone, 0, px, py, pz, ry, rx, ry2, scale);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_model_render_bone_local(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 9, 9);
|
||||
float px, py, pz;
|
||||
float ry, rx, ry2;
|
||||
float scale;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
px = lua_tonumber(L, 3);
|
||||
py = lua_tonumber(L, 4);
|
||||
pz = lua_tonumber(L, 5);
|
||||
|
||||
ry = lua_tonumber(L, 6);
|
||||
rx = lua_tonumber(L, 7);
|
||||
ry2 = lua_tonumber(L, 8);
|
||||
|
||||
scale = lua_tonumber(L, 9);
|
||||
|
||||
render_pmf_bone(screen->pixels, screen->w, screen->h, screen->pitch/4, &tcam,
|
||||
bone, 1, px, py, pz, ry, rx, ry2, scale);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_screen_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushinteger(L, screen->w);
|
||||
lua_pushinteger(L, screen->h);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_client_img_load(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
const char *fname = lua_tostring(L, 1);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
img_t *img = img_load_tga(fname);
|
||||
if(img == NULL)
|
||||
return 0;
|
||||
|
||||
lua_pushlightuserdata(L, img);
|
||||
lua_pushinteger(L, img->head.width);
|
||||
lua_pushinteger(L, img->head.height);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_client_img_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
img_free(img);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_img_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
lua_pushinteger(L, img->head.width);
|
||||
lua_pushinteger(L, img->head.height);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_client_img_blit(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 8);
|
||||
int dx, dy, bw, bh, sx, sy;
|
||||
uint32_t color;
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
dx = lua_tointeger(L, 2);
|
||||
dy = lua_tointeger(L, 3);
|
||||
bw = (top < 4 ? img->head.width : lua_tointeger(L, 4));
|
||||
bh = (top < 5 ? img->head.height : lua_tointeger(L, 5));
|
||||
sx = (top < 6 ? 0 : lua_tointeger(L, 6));
|
||||
sy = (top < 7 ? 0 : lua_tointeger(L, 7));
|
||||
color = (top < 8 ? 0xFFFFFFFF : (uint32_t)lua_tointeger(L, 8));
|
||||
|
||||
render_blit_img(screen->pixels, screen->w, screen->h, screen->pitch/4,
|
||||
img, dx, dy, bw, bh, sx, sy, color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// server functions
|
||||
|
||||
@ -815,9 +75,8 @@ struct icelua_entry icelua_client[] = {
|
||||
{icelua_fn_client_camera_get_pos, "camera_get_pos"},
|
||||
{icelua_fn_client_camera_get_forward, "camera_get_forward"},
|
||||
{icelua_fn_client_screen_get_dims, "screen_get_dims"},
|
||||
{icelua_fn_client_img_load, "img_load"},
|
||||
{icelua_fn_client_img_free, "img_free"},
|
||||
{icelua_fn_client_img_get_dims, "img_get_dims"},
|
||||
{icelua_fn_client_model_render_bone_global, "model_render_bone_global"},
|
||||
{icelua_fn_client_model_render_bone_local, "model_render_bone_local"},
|
||||
{icelua_fn_client_img_blit, "img_blit"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@ -839,8 +98,9 @@ struct icelua_entry icelua_common[] = {
|
||||
{icelua_fn_common_model_bone_get, "model_bone_get"},
|
||||
{icelua_fn_common_model_bone_set, "model_bone_set"},
|
||||
{icelua_fn_common_model_bone_find, "model_bone_find"},
|
||||
{icelua_fn_client_model_render_bone_global, "model_render_bone_global"},
|
||||
{icelua_fn_client_model_render_bone_local, "model_render_bone_local"},
|
||||
{icelua_fn_common_img_load, "img_load"},
|
||||
{icelua_fn_common_img_free, "img_free"},
|
||||
{icelua_fn_common_img_get_dims, "img_get_dims"},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
@ -855,6 +115,9 @@ struct icelua_entry icelua_common_server[] = {
|
||||
|
||||
void icelua_loadfuncs(lua_State *L, char *table, struct icelua_entry *fnlist)
|
||||
{
|
||||
if(L == NULL)
|
||||
return;
|
||||
|
||||
lua_getglobal(L, table);
|
||||
|
||||
while(fnlist->fn != NULL)
|
||||
@ -869,6 +132,9 @@ void icelua_loadfuncs(lua_State *L, char *table, struct icelua_entry *fnlist)
|
||||
|
||||
void icelua_loadbasefuncs(lua_State *L)
|
||||
{
|
||||
if(L == NULL)
|
||||
return;
|
||||
|
||||
// load base library
|
||||
// TODO: whitelist the functions by spawning a new environment.
|
||||
// this is harder than it sounds.
|
||||
@ -884,20 +150,28 @@ void icelua_loadbasefuncs(lua_State *L)
|
||||
|
||||
int icelua_init(void)
|
||||
{
|
||||
int i, argct;
|
||||
|
||||
// create states
|
||||
lstate_client = luaL_newstate();
|
||||
lstate_server = luaL_newstate();
|
||||
lstate_client = (boot_mode & 1 ? luaL_newstate() : NULL);
|
||||
lstate_server = (boot_mode & 2 ? luaL_newstate() : NULL);
|
||||
|
||||
// create tables
|
||||
if(lstate_client != NULL)
|
||||
{
|
||||
lua_newtable(lstate_client);
|
||||
lua_setglobal(lstate_client, "client");
|
||||
lua_newtable(lstate_client);
|
||||
lua_setglobal(lstate_client, "common");
|
||||
}
|
||||
|
||||
if(lstate_server != NULL)
|
||||
{
|
||||
lua_newtable(lstate_server);
|
||||
lua_setglobal(lstate_server, "server");
|
||||
lua_newtable(lstate_server);
|
||||
lua_setglobal(lstate_server, "common");
|
||||
}
|
||||
|
||||
// load stuff into them
|
||||
icelua_loadfuncs(lstate_client, "client", icelua_client);
|
||||
@ -924,31 +198,45 @@ int icelua_init(void)
|
||||
// quick test
|
||||
// TODO: set up a "convert/filter file path" function
|
||||
// TODO: split the client/server inits
|
||||
if(luaL_loadfile(lstate_server, "pkg/base/main_server.lua") != 0)
|
||||
if((lstate_server != NULL) && luaL_loadfile(lstate_server, "pkg/base/main_server.lua") != 0)
|
||||
{
|
||||
printf("ERROR loading server Lua: %s\n", lua_tostring(lstate_server, -1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(luaL_loadfile(lstate_client, "pkg/base/main_client.lua") != 0)
|
||||
if((lstate_client != NULL) && luaL_loadfile(lstate_client, "pkg/base/main_client.lua") != 0)
|
||||
{
|
||||
printf("ERROR loading client Lua: %s\n", lua_tostring(lstate_client, -1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(lua_pcall(lstate_server, 0, 0, 0) != 0)
|
||||
argct = (main_largstart == -1 || (main_largstart >= main_argc)
|
||||
? 0
|
||||
: main_argc - main_largstart);
|
||||
|
||||
if(lstate_server != NULL)
|
||||
{
|
||||
for(i = 0; i < argct; i++)
|
||||
lua_pushstring(lstate_server, main_argv[i+main_largstart]);
|
||||
if(lua_pcall(lstate_server, argct, 0, 0) != 0)
|
||||
{
|
||||
printf("ERROR running server Lua: %s\n", lua_tostring(lstate_server, -1));
|
||||
lua_pop(lstate_server, 1);
|
||||
}
|
||||
lua_pop(lstate_server, 1);
|
||||
}
|
||||
|
||||
if(lua_pcall(lstate_client, 0, 0, 0) != 0)
|
||||
if(lstate_client != NULL)
|
||||
{
|
||||
for(i = 0; i < argct; i++)
|
||||
lua_pushstring(lstate_client, main_argv[i+main_largstart]);
|
||||
if(lua_pcall(lstate_client, argct, 0, 0) != 0)
|
||||
{
|
||||
printf("ERROR running client Lua: %s\n", lua_tostring(lstate_client, -1));
|
||||
lua_pop(lstate_client, 1);
|
||||
}
|
||||
lua_pop(lstate_client, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
117
lua_camera.h
Normal file
117
lua_camera.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_camera_point(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 5);
|
||||
float dx, dy, dz;
|
||||
float zoom = 1.0f, roll = 0.0f;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
if(top >= 4)
|
||||
zoom = lua_tonumber(L, 4);
|
||||
if(top >= 5)
|
||||
roll = lua_tonumber(L, 5);
|
||||
|
||||
//printf("%f\n", zoom);
|
||||
cam_point_dir(&tcam, dx, dy, dz, zoom, roll);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_local(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float dx, dy, dz;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx += dx*tcam.mxx+dy*tcam.myx+dz*tcam.mzx;
|
||||
tcam.mpy += dx*tcam.mxy+dy*tcam.myy+dz*tcam.mzy;
|
||||
tcam.mpz += dx*tcam.mxz+dy*tcam.myz+dz*tcam.mzz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_global(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float dx, dy, dz;
|
||||
|
||||
dx = lua_tonumber(L, 1);
|
||||
dy = lua_tonumber(L, 2);
|
||||
dz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx += dx;
|
||||
tcam.mpy += dy;
|
||||
tcam.mpz += dz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_move_to(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
float px, py, pz;
|
||||
|
||||
px = lua_tonumber(L, 1);
|
||||
py = lua_tonumber(L, 2);
|
||||
pz = lua_tonumber(L, 3);
|
||||
|
||||
tcam.mpx = px;
|
||||
tcam.mpy = py;
|
||||
tcam.mpz = pz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_get_pos(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushnumber(L, tcam.mpx);
|
||||
lua_pushnumber(L, tcam.mpy);
|
||||
lua_pushnumber(L, tcam.mpz);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_client_camera_get_forward(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushnumber(L, tcam.mzx);
|
||||
lua_pushnumber(L, tcam.mzy);
|
||||
lua_pushnumber(L, tcam.mzz);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_client_screen_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushinteger(L, screen->w);
|
||||
lua_pushinteger(L, screen->h);
|
||||
|
||||
return 2;
|
||||
}
|
29
lua_fetch.h
Normal file
29
lua_fetch.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// common functions
|
||||
int icelua_fn_common_fetch(lua_State *L)
|
||||
{
|
||||
// TODO!
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_fetch_block(lua_State *L)
|
||||
{
|
||||
// TODO!
|
||||
return 0;
|
||||
}
|
88
lua_image.h
Normal file
88
lua_image.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_img_blit(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 8);
|
||||
int dx, dy, bw, bh, sx, sy;
|
||||
uint32_t color;
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
dx = lua_tointeger(L, 2);
|
||||
dy = lua_tointeger(L, 3);
|
||||
bw = (top < 4 ? img->head.width : lua_tointeger(L, 4));
|
||||
bh = (top < 5 ? img->head.height : lua_tointeger(L, 5));
|
||||
sx = (top < 6 ? 0 : lua_tointeger(L, 6));
|
||||
sy = (top < 7 ? 0 : lua_tointeger(L, 7));
|
||||
color = (top < 8 ? 0xFFFFFFFF : (uint32_t)lua_tointeger(L, 8));
|
||||
|
||||
render_blit_img(screen->pixels, screen->w, screen->h, screen->pitch/4,
|
||||
img, dx, dy, bw, bh, sx, sy, color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// common functions
|
||||
int icelua_fn_common_img_load(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
const char *fname = lua_tostring(L, 1);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
img_t *img = img_load_tga(fname);
|
||||
if(img == NULL)
|
||||
return 0;
|
||||
|
||||
lua_pushlightuserdata(L, img);
|
||||
lua_pushinteger(L, img->head.width);
|
||||
lua_pushinteger(L, img->head.height);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int icelua_fn_common_img_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
img_free(img);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_img_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
img_t *img = lua_touserdata(L, 1);
|
||||
if(img == NULL)
|
||||
return luaL_error(L, "not an image");
|
||||
|
||||
lua_pushinteger(L, img->head.width);
|
||||
lua_pushinteger(L, img->head.height);
|
||||
|
||||
return 2;
|
||||
}
|
37
lua_input.h
Normal file
37
lua_input.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_mouse_lock_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
SDL_WM_GrabInput(lua_toboolean(L, 1)
|
||||
? SDL_GRAB_ON
|
||||
: SDL_GRAB_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_mouse_visible_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
SDL_ShowCursor(lua_toboolean(L, 1));
|
||||
|
||||
return 0;
|
||||
}
|
212
lua_map.h
Normal file
212
lua_map.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// common functions
|
||||
int icelua_fn_common_map_get_dims(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, just give off nils
|
||||
if(map == NULL)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
lua_pushinteger(L, map->xlen);
|
||||
lua_pushinteger(L, map->ylen);
|
||||
lua_pushinteger(L, map->zlen);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
int icelua_fn_common_map_pillar_get(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
int px, pz;
|
||||
int i;
|
||||
|
||||
px = lua_tointeger(L, 1);
|
||||
pz = lua_tointeger(L, 2);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, return nil
|
||||
if(map == NULL)
|
||||
return 0;
|
||||
|
||||
// get a pillar
|
||||
uint8_t *p = map->pillars[(pz&(map->zlen-1))*map->xlen+(px&(map->xlen-1))];
|
||||
|
||||
// build the list
|
||||
int llen = 4*((255&(int)*p)+1);
|
||||
lua_createtable(L, llen, 0);
|
||||
p += 4;
|
||||
|
||||
for(i = 1; i <= llen; i++)
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushinteger(L, *(p++));
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_map_pillar_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 3, 3);
|
||||
int px, pz, tlen;
|
||||
int i;
|
||||
|
||||
px = lua_tointeger(L, 1);
|
||||
pz = lua_tointeger(L, 2);
|
||||
if(!lua_istable(L, 3))
|
||||
return luaL_error(L, "expected a table, got something else");
|
||||
tlen = lua_objlen(L, 3);
|
||||
|
||||
map_t *map = (L == lstate_server ? svmap : clmap);
|
||||
|
||||
// if no map, ignore (for now)
|
||||
if(map == NULL)
|
||||
return 0;
|
||||
|
||||
// validate that the table is not TOO large and is 4-byte aligned wrt size
|
||||
if((tlen&3) || tlen > 1024)
|
||||
return luaL_error(L, "table length %d invalid", tlen);
|
||||
|
||||
// validate the table's input range
|
||||
for(i = 0; i < tlen; i++)
|
||||
{
|
||||
lua_pushinteger(L, 1+i);
|
||||
lua_gettable(L, 3);
|
||||
int v = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if(v < 0 || v > 255)
|
||||
return luaL_error(L, "value at index %d out of unsigned byte range (%d)"
|
||||
, 1+i, v);
|
||||
}
|
||||
|
||||
// validate the table data
|
||||
i = 0;
|
||||
for(;;)
|
||||
{
|
||||
lua_pushinteger(L, 1+i+0);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+1);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+2);
|
||||
lua_gettable(L, 3);
|
||||
lua_pushinteger(L, 1+i+3);
|
||||
lua_gettable(L, 3);
|
||||
int n = lua_tointeger(L, -4);
|
||||
int s = lua_tointeger(L, -3);
|
||||
int e = lua_tointeger(L, -2);
|
||||
int a = lua_tointeger(L, -1);
|
||||
lua_pop(L, 4);
|
||||
|
||||
//printf("%i %i | %i %i | %i %i %i %i\n",px,pz,i,tlen,n,s,e,a);
|
||||
|
||||
// Note, we are not supporting the shenanigans you can do in VOXLAP.
|
||||
// Especially considering that editing said shenanigans causes issues.
|
||||
// Also noting that said shenanigans weren't all that exploited,
|
||||
// VOXLAP automatically corrects shenanigans when you edit stuff,
|
||||
// and pyspades has no support for such shenanigans.
|
||||
if(e+1 < s)
|
||||
return luaL_error(L, "pillar has end+1 < start (%d < %d)"
|
||||
, e+1, s);
|
||||
if(i != 0 && s < a)
|
||||
return luaL_error(L, "pillar has start < air (%d < %d)"
|
||||
, s, a);
|
||||
if(n != 0 && n-1 < e-s+1)
|
||||
return luaL_error(L, "pillar has length < top length (%d < %d)"
|
||||
, n-1, e-s+1);
|
||||
|
||||
|
||||
// NOTE: this doesn't validate the BGRT (colour/type) entries.
|
||||
int la = 0;
|
||||
if(n == 0)
|
||||
{
|
||||
int exlen = (e-s+1)*4+i+4;
|
||||
if(exlen != tlen)
|
||||
return luaL_error(L, "pillar table len should be %d, got %d instead"
|
||||
, exlen, tlen);
|
||||
break;
|
||||
} else {
|
||||
i += 4*n;
|
||||
// should always be colour on the bottom!
|
||||
if(i > tlen-4)
|
||||
return luaL_error(L, "pillar table overflow when validating");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// expand the pillar data if necessary
|
||||
int idx = (pz&(map->zlen-1))*map->xlen+(px&(map->xlen-1));
|
||||
uint8_t *p = map->pillars[idx];
|
||||
if((p[0]+1)*4 < tlen)
|
||||
{
|
||||
p = map->pillars[idx] = realloc(p, tlen+4);
|
||||
p[0] = (tlen>>2)-1;
|
||||
}
|
||||
|
||||
// transfer the table data
|
||||
p += 4;
|
||||
for(i = 1; i <= tlen; i++)
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
lua_gettable(L, 3);
|
||||
*(p++) = (uint8_t)lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
force_redraw = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_map_fog_get(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 0);
|
||||
|
||||
lua_pushinteger(L, (fog_color>>16)&255);
|
||||
lua_pushinteger(L, (fog_color>>8)&255);
|
||||
lua_pushinteger(L, (fog_color)&255);
|
||||
lua_pushnumber(L, fog_distance);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
int icelua_fn_client_map_fog_set(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 4, 4);
|
||||
|
||||
int r = lua_tointeger(L, 1)&255;
|
||||
int g = lua_tointeger(L, 2)&255;
|
||||
int b = lua_tointeger(L, 3)&255;
|
||||
fog_distance = lua_tonumber(L, 4);
|
||||
if(fog_distance < 5.0f)
|
||||
fog_distance = 5.0f;
|
||||
if(fog_distance > FOG_MAX_DISTANCE)
|
||||
fog_distance = FOG_MAX_DISTANCE;
|
||||
|
||||
fog_color = (r<<16)|(g<<8)|b;
|
||||
force_redraw = 1;
|
||||
|
||||
return 4;
|
||||
}
|
381
lua_model.h
Normal file
381
lua_model.h
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
int icelua_fn_common_model_new(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 0, 1);
|
||||
int bonemax = 5;
|
||||
|
||||
if(top >= 1)
|
||||
bonemax = lua_tointeger(L, 1);
|
||||
if(bonemax < 0 || bonemax >= MODEL_BONE_MAX)
|
||||
return luaL_error(L, "cannot have %d bones, max is %d", bonemax, MODEL_BONE_MAX);
|
||||
|
||||
model_t *pmf = model_new(bonemax);
|
||||
|
||||
// TODO: add this to a clean-up linked list or something
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_load_pmf(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
const char *fname = lua_tostring(L, 1);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
model_t *pmf = model_load_pmf(fname);
|
||||
|
||||
// TODO: add this to a clean-up linked list or something
|
||||
if(pmf == NULL)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_save_pmf(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
const char *fname = lua_tostring(L, 2);
|
||||
if(fname == NULL)
|
||||
return luaL_error(L, "filename must be a string");
|
||||
|
||||
lua_pushboolean(L, !model_save_pmf(pmf, fname));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
model_free(pmf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_len(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 1);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
lua_pushinteger(L, pmf->bonelen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_new(lua_State *L)
|
||||
{
|
||||
// TODO: check for size limit
|
||||
|
||||
int top = icelua_assert_stack(L, 1, 2);
|
||||
int ptmax = 20;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
if(top >= 2)
|
||||
ptmax = lua_tointeger(L, 2);
|
||||
if(ptmax < 0 || ptmax >= MODEL_POINT_MAX)
|
||||
return luaL_error(L, "cannot have %d points, max is %d", ptmax, MODEL_POINT_MAX);
|
||||
|
||||
// ensure there is room for this bone
|
||||
int tsize = pmf->bonelen+1;
|
||||
|
||||
if(pmf->bonelen >= pmf->bonemax)
|
||||
{
|
||||
int csize = (pmf->bonemax*3)/2+1;
|
||||
if(csize < tsize)
|
||||
csize = tsize;
|
||||
|
||||
pmf = model_extend(pmf, csize);
|
||||
}
|
||||
|
||||
// now add it
|
||||
model_bone_t *bone = model_bone_new(pmf, ptmax);
|
||||
|
||||
lua_pushlightuserdata(L, pmf);
|
||||
lua_pushinteger(L, bone->parent_idx);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_free(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 1, 2);
|
||||
int boneidx;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
|
||||
model_bone_free(pmf->bones[boneidx]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_get(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
// push args
|
||||
lua_pushstring(L, bone->name);
|
||||
lua_createtable(L, bone->ptlen, 0);
|
||||
|
||||
// fill the table
|
||||
for(i = 0; i < bone->ptlen; i++)
|
||||
{
|
||||
model_point_t *pt = &(bone->pts[i]);
|
||||
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_createtable(L, 0, 7);
|
||||
|
||||
lua_pushinteger(L, pt->radius);
|
||||
lua_setfield(L, -2, "radius");
|
||||
|
||||
lua_pushinteger(L, pt->x);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushinteger(L, pt->y);
|
||||
lua_setfield(L, -2, "y");
|
||||
lua_pushinteger(L, pt->z);
|
||||
lua_setfield(L, -2, "z");
|
||||
|
||||
lua_pushinteger(L, pt->r);
|
||||
lua_setfield(L, -2, "r");
|
||||
lua_pushinteger(L, pt->g);
|
||||
lua_setfield(L, -2, "g");
|
||||
lua_pushinteger(L, pt->b);
|
||||
lua_setfield(L, -2, "b");
|
||||
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_set(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 4, 4);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
const char *name = lua_tostring(L, 3);
|
||||
if(name == NULL)
|
||||
return luaL_error(L, "bone name cannot be nil");
|
||||
if(strlen(name) > 15)
|
||||
return luaL_error(L, "bone name too long, was %d chars, max is 15", strlen(name));
|
||||
|
||||
if(!lua_istable(L, 4))
|
||||
return luaL_error(L, "expected a table, got something else");
|
||||
|
||||
// check if the bone is large enough
|
||||
|
||||
int tsize = lua_objlen(L, 4);
|
||||
|
||||
if(tsize > bone->ptmax)
|
||||
{
|
||||
int csize = (bone->ptmax*3)/2+1;
|
||||
if(csize < tsize)
|
||||
csize = tsize;
|
||||
|
||||
//printf("bone extend %i %i %i\n", bone->ptmax, tsize, csize);
|
||||
bone = model_bone_extend(bone, csize);
|
||||
}
|
||||
|
||||
// set the bone's name
|
||||
strcpy(bone->name, name);
|
||||
|
||||
// load the table's contents
|
||||
bone->ptlen = 0;
|
||||
for(i = 0; i < tsize; i++)
|
||||
{
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_gettable(L, 4);
|
||||
|
||||
// note, bones will be rejected if:
|
||||
// - radius,x,y,z,r,g,b are missing
|
||||
int radius = icelua_force_get_integer(L, -1, "radius");
|
||||
int x = icelua_force_get_integer(L, -1, "x");
|
||||
int y = icelua_force_get_integer(L, -1, "y");
|
||||
int z = icelua_force_get_integer(L, -1, "z");
|
||||
int r = icelua_force_get_integer(L, -1, "r");
|
||||
int g = icelua_force_get_integer(L, -1, "g");
|
||||
int b = icelua_force_get_integer(L, -1, "b");
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
// - 0 <= radius < 65536 fails
|
||||
if(radius < 0 || radius >= 65536)
|
||||
return luaL_error(L, "radius out of range of 0 <= %d < 65536", radius);
|
||||
|
||||
// - -32768 <= x,y,z < 32768 fails
|
||||
if(x < -32768 || x >= 32768)
|
||||
return luaL_error(L, "x out of range of -32768 <= %d < 32768", x);
|
||||
if(y < -32768 || y >= 32768)
|
||||
return luaL_error(L, "y out of range of -32768 <= %d < 32768", x);
|
||||
if(z < -32768 || z >= 32768)
|
||||
return luaL_error(L, "z out of range of -32768 <= %d < 32768", x);
|
||||
|
||||
// - 0 <= r,g,b < 256 fails
|
||||
if(r < 0 || r >= 256)
|
||||
return luaL_error(L, "r out of range of 0 <= %d < 256", r);
|
||||
if(g < 0 || g >= 256)
|
||||
return luaL_error(L, "g out of range of 0 <= %d < 256", g);
|
||||
if(b < 0 || b >= 256)
|
||||
return luaL_error(L, "b out of range of 0 <= %d < 256", b);
|
||||
|
||||
// add it in!
|
||||
model_point_t *pt = &(bone->pts[i]);
|
||||
|
||||
pt->radius = radius;
|
||||
pt->x = x, pt->y = y, pt->z = z;
|
||||
pt->r = r, pt->g = g, pt->b = b;
|
||||
pt->resv1 = 0;
|
||||
|
||||
bone->ptlen++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_common_model_bone_find(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = icelua_assert_stack(L, 2, 2);
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
const char *name = lua_tostring(L, 2);
|
||||
if(name == NULL)
|
||||
return luaL_error(L, "name must be a string");
|
||||
|
||||
for(i = 0; i < pmf->bonemax; i++)
|
||||
{
|
||||
model_bone_t *bone = pmf->bones[i];
|
||||
|
||||
if(!strcmp(bone->name, name))
|
||||
{
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// client functions
|
||||
int icelua_fn_client_model_render_bone_global(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 9, 9);
|
||||
float px, py, pz;
|
||||
float ry, rx, ry2;
|
||||
float scale;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
px = lua_tonumber(L, 3);
|
||||
py = lua_tonumber(L, 4);
|
||||
pz = lua_tonumber(L, 5);
|
||||
|
||||
ry = lua_tonumber(L, 6);
|
||||
rx = lua_tonumber(L, 7);
|
||||
ry2 = lua_tonumber(L, 8);
|
||||
|
||||
scale = lua_tonumber(L, 9);
|
||||
|
||||
render_pmf_bone(screen->pixels, screen->w, screen->h, screen->pitch/4, &tcam,
|
||||
bone, 0, px, py, pz, ry, rx, ry2, scale);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icelua_fn_client_model_render_bone_local(lua_State *L)
|
||||
{
|
||||
int top = icelua_assert_stack(L, 9, 9);
|
||||
float px, py, pz;
|
||||
float ry, rx, ry2;
|
||||
float scale;
|
||||
|
||||
model_t *pmf = lua_touserdata(L, 1);
|
||||
if(pmf == NULL)
|
||||
return luaL_error(L, "not a model");
|
||||
|
||||
int boneidx = lua_tointeger(L, 2);
|
||||
if(boneidx < 0 || boneidx >= pmf->bonelen)
|
||||
return luaL_error(L, "bone index %d out of range, len is %d", boneidx, pmf->bonelen);
|
||||
model_bone_t *bone = pmf->bones[boneidx];
|
||||
|
||||
px = lua_tonumber(L, 3);
|
||||
py = lua_tonumber(L, 4);
|
||||
pz = lua_tonumber(L, 5);
|
||||
|
||||
ry = lua_tonumber(L, 6);
|
||||
rx = lua_tonumber(L, 7);
|
||||
ry2 = lua_tonumber(L, 8);
|
||||
|
||||
scale = lua_tonumber(L, 9);
|
||||
|
||||
render_pmf_bone(screen->pixels, screen->w, screen->h, screen->pitch/4, &tcam,
|
||||
bone, 1, px, py, pz, ry, rx, ry2, scale);
|
||||
|
||||
return 0;
|
||||
}
|
15
main.c
15
main.c
@ -31,6 +31,10 @@ int boot_mode = 0; // bit 0 = client, bit 1 = server
|
||||
|
||||
char *fnmap = "mesa.vxl";
|
||||
|
||||
int main_argc;
|
||||
char **main_argv;
|
||||
int main_largstart = -1;
|
||||
|
||||
int error_sdl(char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", msg, SDL_GetError());
|
||||
@ -128,6 +132,7 @@ int update_client(void)
|
||||
lua_pop(lstate_client, 1);
|
||||
return 1;
|
||||
}
|
||||
if(!(boot_mode & 2))
|
||||
sec_wait += lua_tonumber(lstate_client, -1);
|
||||
lua_pop(lstate_client, 1);
|
||||
|
||||
@ -358,7 +363,7 @@ int print_usage(char *rname)
|
||||
fprintf(stderr, "usage:\n"
|
||||
"\tfor clients:\n"
|
||||
"\t\t%s -c address port {clargs}\n"
|
||||
"\tfor servers:\n"
|
||||
"\tfor servers (quick-start, not recommended for anything serious!):\n"
|
||||
"\t\t%s -s port mod {args}\n"
|
||||
"\tfor dedicated servers:\n"
|
||||
"\t\t%s -d port mod {args}\n"
|
||||
@ -382,6 +387,9 @@ int main(int argc, char *argv[])
|
||||
if(argc <= 1)
|
||||
return print_usage(argv[0]);
|
||||
|
||||
main_argc = argc;
|
||||
main_argv = argv;
|
||||
|
||||
if(!strcmp(argv[1], "-c"))
|
||||
{
|
||||
if(argc <= 3)
|
||||
@ -390,6 +398,7 @@ int main(int argc, char *argv[])
|
||||
char *net_addr = argv[2];
|
||||
int net_port = atoi(argv[3]);
|
||||
printf("TODO: connect to \"%s\" port %i\n", net_addr, net_port);
|
||||
main_largstart = 4;
|
||||
|
||||
boot_mode = 1;
|
||||
return 101;
|
||||
@ -400,6 +409,7 @@ int main(int argc, char *argv[])
|
||||
int net_port = atoi(argv[2]);
|
||||
char *net_mod = argv[3];
|
||||
printf("TODO: run a server on port %i, mod \"%s\"\n", net_port, net_mod);
|
||||
main_largstart = 4;
|
||||
if(argc > 4)
|
||||
fnmap = argv[4];
|
||||
|
||||
@ -411,9 +421,10 @@ int main(int argc, char *argv[])
|
||||
int net_port = atoi(argv[2]);
|
||||
char *net_mod = argv[3];
|
||||
printf("TODO: run a ded server on port %i, mod \"%s\"\n", net_port, net_mod);
|
||||
return 101;
|
||||
main_largstart = 4;
|
||||
|
||||
boot_mode = 2;
|
||||
return 101;
|
||||
} else {
|
||||
return print_usage(argv[0]);
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ OBJS = \
|
||||
$(OBJDIR)/vecmath.o \
|
||||
$(OBJDIR)/map.o $(OBJDIR)/model.o \
|
||||
$(OBJDIR)/img.o $(OBJDIR)/render.o \
|
||||
$(OBJDIR)/lua.o $(OBJDIR)/network.o
|
||||
$(OBJDIR)/lua.o $(OBJDIR)/network.o \
|
||||
$(OBJDIR)/path.o
|
||||
|
||||
all: $(OBJDIR) $(BINNAME) $(TOOLS)
|
||||
|
||||
@ -21,6 +22,9 @@ $(OBJDIR):
|
||||
$(BINNAME): $(OBJS)
|
||||
$(CC) -o $(BINNAME) $(LDFLAGS) $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJDIR)/lua.o: lua.c lua_*.h $(INCLUDES)
|
||||
$(CC) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c $(INCLUDES)
|
||||
$(CC) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
|
2
opencmd.bat
Normal file
2
opencmd.bat
Normal file
@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
command
|
32
path.c
Normal file
32
path.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
This file is part of Iceball.
|
||||
|
||||
Iceball is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Iceball 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
char *path_filter(const char *instr)
|
||||
{
|
||||
#ifdef WIN32
|
||||
// TODO? filter for Windows?
|
||||
#endif
|
||||
return strdup(instr);
|
||||
}
|
||||
|
||||
int path_get_type(const char *path)
|
||||
{
|
||||
// TODO!
|
||||
return PATH_PKG;
|
||||
}
|
183
pkg/base/common.lua
Normal file
183
pkg/base/common.lua
Normal file
@ -0,0 +1,183 @@
|
||||
--[[
|
||||
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/>.
|
||||
]]
|
||||
|
||||
-- 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 DIR_PKG_ROOT.."/map"
|
||||
|
||||
MAP_DEFAULT = MAP_DEFAULT or DIR_PKG_MAP.."/mesa.vxl"
|
||||
|
||||
LIB_LIST = LIB_LIST or {
|
||||
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_vector.lua",
|
||||
|
||||
DIR_PKG_LIB.."/obj_player.lua",
|
||||
DIR_PKG_LIB.."/obj_intent.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_TILT_SLOWDOWN = false -- TODO!
|
||||
MODE_TILT_DOWN_NOCLIMB = false -- TODO!
|
||||
|
||||
MODE_DELAY_SPADE_DIG = 1.0
|
||||
MODE_DELAY_SPADE_HIT = 0.25
|
||||
MODE_DELAY_BLOCK_BUILD = 0.5
|
||||
MODE_DELAY_TOOL_CHANGE = 0.4
|
||||
|
||||
-- tools
|
||||
TOOL_SPADE = 0
|
||||
TOOL_BLOCK = 1
|
||||
TOOL_GUN = 2
|
||||
TOOL_NADE = 3
|
||||
|
||||
-- weapons
|
||||
WPN_RIFLE = 1
|
||||
WPN_SHOTTY = 2
|
||||
|
||||
weapons = {
|
||||
[WPN_RIFLE] = {
|
||||
-- version: 0.60 with spread removed completely
|
||||
dmg_head = 100,
|
||||
dmg_body = 49,
|
||||
dmg_limb = 33,
|
||||
|
||||
ammo_clip = 10,
|
||||
ammo_reserve = 50,
|
||||
ammo_pallets = 1,
|
||||
time_fire = 1/2,
|
||||
time_reload = 2.5,
|
||||
is_reload_perclip = false,
|
||||
|
||||
spread = 0.0, -- THAT'S RIGHT, THE 0.75 RIFLE SUCKS
|
||||
recoil_x = 0.0001,
|
||||
recoil_y = -0.05,
|
||||
|
||||
basename = "rifle",
|
||||
|
||||
fn_tick = function(sec_current, sec_delta, plr, wpn, wpnstatic)
|
||||
if wpn.firing and sec_current < wpn.t_fire then
|
||||
-- TODO: actually fire gun
|
||||
|
||||
wpn.t_fire = wpn.t_fire + wpnstatic.time_fire
|
||||
if wpn.t_fire < sec_current then
|
||||
wpn.t_fire = sec_current
|
||||
end
|
||||
|
||||
-- TODO: poll: do we want to require a new click per shot?
|
||||
end
|
||||
end,
|
||||
|
||||
enabled = true,
|
||||
},
|
||||
[WPN_SHOTTY] = {
|
||||
-- version: something quite different.
|
||||
-- TODO: get the balance right!
|
||||
dmg_head = 26,
|
||||
dmg_body = 23,
|
||||
dmg_limb = 19,
|
||||
|
||||
ammo_clip = 10,
|
||||
ammo_reserve = 50,
|
||||
ammo_pallets = 16,
|
||||
time_fire = 1/15,
|
||||
time_reload = 2.5,
|
||||
is_reload_perclip = false,
|
||||
|
||||
spread = 0.015, -- No, this should not be good at range.
|
||||
recoil_x = 0.003,
|
||||
recoil_y = -0.12,
|
||||
|
||||
basename = "shotty",
|
||||
|
||||
enabled = false,
|
||||
},
|
||||
}
|
||||
|
||||
-- teams
|
||||
teams = {
|
||||
[0] = {
|
||||
name = "Blue Master Race",
|
||||
color_mdl = {16,128,32},
|
||||
color_chat = {0,255,0},
|
||||
},
|
||||
[1] = {
|
||||
name = "Green Master Race",
|
||||
color_mdl = {16,32,128},
|
||||
color_chat = {0,0,255},
|
||||
},
|
||||
}
|
||||
|
||||
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
|
@ -15,10 +15,10 @@
|
||||
along with Ice Lua Components. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
do
|
||||
if client then
|
||||
-- load images
|
||||
local img_font_numbers = client.img_load("pkg/base/gfx/font-numbers.tga")
|
||||
local img_font_mini = client.img_load("pkg/base/gfx/font-mini.tga")
|
||||
local img_font_numbers = common.img_load("pkg/base/gfx/font-numbers.tga")
|
||||
local img_font_mini = common.img_load("pkg/base/gfx/font-mini.tga")
|
||||
--[[
|
||||
client.img_free(img_font_numbers)
|
||||
img_font_numbers = nil -- PLEASE DO THIS, GUYS!
|
||||
|
@ -16,18 +16,9 @@
|
||||
]]
|
||||
|
||||
print("pkg/base/main_client.lua starting")
|
||||
print(...)
|
||||
|
||||
-- load libs
|
||||
dofile("pkg/base/lib_collect.lua")
|
||||
dofile("pkg/base/lib_gui.lua")
|
||||
dofile("pkg/base/lib_map.lua")
|
||||
dofile("pkg/base/lib_namegen.lua")
|
||||
dofile("pkg/base/lib_pmf.lua")
|
||||
dofile("pkg/base/lib_sdlkey.lua")
|
||||
dofile("pkg/base/lib_vector.lua")
|
||||
|
||||
dofile("pkg/base/obj_player.lua")
|
||||
dofile("pkg/base/obj_intent.lua")
|
||||
dofile("pkg/base/common.lua")
|
||||
|
||||
-- define keys
|
||||
BTSK_FORWARD = SDLK_w
|
||||
@ -54,125 +45,6 @@ BTSK_QUIT = SDLK_ESCAPE
|
||||
|
||||
BTSK_DEBUG = SDLK_F1
|
||||
|
||||
-- mode stuff
|
||||
MODE_CHEAT_FLY = false
|
||||
|
||||
MODE_AUTOCLIMB = true
|
||||
MODE_AIRJUMP = false
|
||||
MODE_SOFTCROUCH = true
|
||||
|
||||
MODE_TILT_SLOWDOWN = false -- TODO!
|
||||
MODE_TILT_DOWN_NOCLIMB = false -- TODO!
|
||||
|
||||
MODE_DELAY_SPADE_DIG = 1.0
|
||||
MODE_DELAY_SPADE_HIT = 0.25
|
||||
MODE_DELAY_BLOCK_BUILD = 0.5
|
||||
MODE_DELAY_TOOL_CHANGE = 0.4
|
||||
|
||||
-- tools
|
||||
TOOL_SPADE = 0
|
||||
TOOL_BLOCK = 1
|
||||
TOOL_GUN = 2
|
||||
TOOL_NADE = 3
|
||||
|
||||
-- weapons
|
||||
WPN_RIFLE = 1
|
||||
WPN_SHOTTY = 2
|
||||
|
||||
weapons = {
|
||||
[WPN_RIFLE] = {
|
||||
-- version: 0.60 with spread removed completely
|
||||
dmg_head = 100,
|
||||
dmg_body = 49,
|
||||
dmg_limb = 33,
|
||||
|
||||
ammo_clip = 10,
|
||||
ammo_reserve = 50,
|
||||
ammo_pallets = 1,
|
||||
time_fire = 1/2,
|
||||
time_reload = 2.5,
|
||||
is_reload_perclip = false,
|
||||
|
||||
spread = 0.0, -- THAT'S RIGHT, THE 0.75 RIFLE SUCKS
|
||||
recoil_x = 0.0001,
|
||||
recoil_y = -0.05,
|
||||
|
||||
basename = "rifle",
|
||||
|
||||
enabled = true,
|
||||
},
|
||||
[WPN_SHOTTY] = {
|
||||
-- version: something quite different.
|
||||
-- TODO: get the balance right!
|
||||
dmg_head = 26,
|
||||
dmg_body = 23,
|
||||
dmg_limb = 19,
|
||||
|
||||
ammo_clip = 10,
|
||||
ammo_reserve = 50,
|
||||
ammo_pallets = 16,
|
||||
time_fire = 1/15,
|
||||
time_reload = 2.5,
|
||||
is_reload_perclip = false,
|
||||
|
||||
spread = 0.015, -- No, this should not be good at range.
|
||||
recoil_x = 0.003,
|
||||
recoil_y = -0.12,
|
||||
|
||||
basename = "shotty",
|
||||
|
||||
enabled = false,
|
||||
},
|
||||
}
|
||||
|
||||
-- teams
|
||||
teams = {
|
||||
[0] = {
|
||||
name = "Blue Master Race",
|
||||
color_mdl = {16,128,32},
|
||||
color_chat = {0,255,0},
|
||||
},
|
||||
[1] = {
|
||||
name = "Green Master Race",
|
||||
color_mdl = {16,32,128},
|
||||
color_chat = {0,0,255},
|
||||
},
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
players = {max = 32, current = 1}
|
||||
|
||||
-- set stuff
|
||||
@ -275,17 +147,18 @@ end
|
||||
|
||||
function h_tick_init(sec_current, sec_delta)
|
||||
local i
|
||||
local squads = {[0]={},[1]={}}
|
||||
--[[local squads = {[0]={},[1]={}}
|
||||
for i=1,4 do
|
||||
squads[0][i] = name_generate()
|
||||
squads[1][i] = name_generate()
|
||||
end
|
||||
end]]
|
||||
|
||||
for i=1,players.max do
|
||||
players[i] = new_player({
|
||||
name = name_generate(),
|
||||
squad = squads[math.fmod(i-1,2)][
|
||||
math.fmod(math.floor((i-1)/2),4)+1],
|
||||
--[[squad = squads[math.fmod(i-1,2)][
|
||||
math.fmod(math.floor((i-1)/2),4)+1],]]
|
||||
squad = nil,
|
||||
team = math.fmod(i-1,2), -- 0 == blue, 1 == green
|
||||
weapon = WPN_RIFLE,
|
||||
})
|
||||
@ -426,10 +299,20 @@ function client.hook_render()
|
||||
players[players.current].show_hud()
|
||||
end
|
||||
|
||||
-- load map
|
||||
map_fname = ...
|
||||
map_fname = map_fname or MAP_DEFAULT
|
||||
|
||||
-- TODO: *.icemap support
|
||||
--map_loaded = common.map_load(map_fname, "vxl")
|
||||
--or common.map_load(map_fname, "icemap")
|
||||
|
||||
print(client.map_fog_get())
|
||||
client.map_fog_set(24,0,32,60)
|
||||
--client.map_fog_set(24,0,32,60)
|
||||
client.map_fog_set(192,238,255,60)
|
||||
print(client.map_fog_get())
|
||||
|
||||
|
||||
print("pkg/base/main_client.lua loaded.")
|
||||
|
||||
--dofile("pkg/base/plug_snow.lua")
|
||||
|
@ -16,16 +16,9 @@
|
||||
]]
|
||||
|
||||
print("pkg/base/main_server.lua starting")
|
||||
print(...)
|
||||
|
||||
dofile("pkg/base/lib_collect.lua")
|
||||
dofile("pkg/base/lib_map.lua")
|
||||
dofile("pkg/base/lib_namegen.lua")
|
||||
dofile("pkg/base/lib_pmf.lua")
|
||||
dofile("pkg/base/lib_sdlkey.lua")
|
||||
dofile("pkg/base/lib_vector.lua")
|
||||
|
||||
dofile("pkg/base/obj_player.lua")
|
||||
dofile("pkg/base/obj_intent.lua")
|
||||
dofile("pkg/base/common.lua")
|
||||
|
||||
function server.hook_tick(sec_current, sec_delta)
|
||||
--print("tick",sec_current,sec_delta)
|
||||
|
@ -327,9 +327,13 @@ function new_player(settings)
|
||||
local fwx,fwy,fwz
|
||||
fwx,fwy,fwz = sya*cxa, sxa, cya*cxa
|
||||
client.camera_point(fwx, fwy, fwz, this.zoom, 0.0)
|
||||
|
||||
-- offset by eye pos
|
||||
-- slightly cheating here.
|
||||
client.camera_move_global(sya*0.4, 0, cya*0.4)
|
||||
end
|
||||
|
||||
function this.render_tool()
|
||||
function this.render()
|
||||
local ays,ayc,axs,axc
|
||||
ays = math.sin(this.angy)
|
||||
ayc = math.cos(this.angy)
|
||||
@ -346,6 +350,20 @@ function new_player(settings)
|
||||
local hand_y2 = 0.5
|
||||
local hand_z2 = -ays*0.4
|
||||
|
||||
local leg_x1 = -ayc*0.2
|
||||
local leg_y1 = 1.5
|
||||
local leg_z1 = ays*0.2
|
||||
|
||||
local leg_x2 = ayc*0.2
|
||||
local leg_y2 = 1.5
|
||||
local leg_z2 = -ays*0.2
|
||||
|
||||
if this.crouching then
|
||||
-- TODO make this look less crap
|
||||
leg_y1 = leg_y1 - 1
|
||||
leg_y2 = leg_y2 - 1
|
||||
end
|
||||
|
||||
local mdl_x = hand_x1+axc*ays*0.8
|
||||
local mdl_y = hand_y1+axs*0.8
|
||||
local mdl_z = hand_z1+axc*ayc*0.8
|
||||
@ -368,37 +386,33 @@ function new_player(settings)
|
||||
0.0, -this.angx, this.angy, 0.5)
|
||||
end
|
||||
|
||||
local swing = math.sin(rotpos/30*2)
|
||||
*math.min(1.0, math.sqrt(
|
||||
this.vx*this.vx
|
||||
+this.vz*this.vz)/8.0)
|
||||
*math.pi/4.0
|
||||
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_arm,
|
||||
this.x+hand_x1, this.y+this.jerkoffs+hand_y1, this.z+hand_z1,
|
||||
0.0, this.angx-math.pi/2, this.angy-math.pi, 2.0)
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_arm,
|
||||
this.x+hand_x2, this.y+this.jerkoffs+hand_y2, this.z+hand_z2,
|
||||
0.0, this.angx-math.pi/2, this.angy-math.pi, 2.0)
|
||||
end
|
||||
0.0, 0-math.pi/4+swing, this.angy-math.pi, 2.0)
|
||||
|
||||
function this.render()
|
||||
local ays,ayc,axs,axc
|
||||
ays = math.sin(this.angy)
|
||||
ayc = math.cos(this.angy)
|
||||
axs = math.sin(this.angx)
|
||||
axc = math.cos(this.angx)
|
||||
|
||||
this.render_tool()
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_leg,
|
||||
this.x+leg_x1, this.y+this.jerkoffs+leg_y1, this.z+leg_z1,
|
||||
0.0, swing, this.angy-math.pi, 2.2)
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_leg,
|
||||
this.x+leg_x2, this.y+this.jerkoffs+leg_y2, this.z+leg_z2,
|
||||
0.0, -swing, this.angy-math.pi, 2.2)
|
||||
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_head,
|
||||
this.x, this.y+this.jerkoffs, this.z,
|
||||
0.0, -this.angx, -this.angy, 1)
|
||||
0.0, this.angx, this.angy-math.pi, 1)
|
||||
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_body,
|
||||
this.x, this.y+this.jerkoffs+0.8, this.z,
|
||||
0.0, -this.angx, -this.angy, 1.5)
|
||||
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_leg,
|
||||
this.x, this.y+this.jerkoffs+1.5, this.z-0.2,
|
||||
0.0, -this.angx, -this.angy, 2.2)
|
||||
client.model_render_bone_global(this.mdl_player, mdl_player_leg,
|
||||
this.x, this.y+this.jerkoffs+1.5, this.z+0.2,
|
||||
0.0, -this.angx, -this.angy, 2.2)
|
||||
0.0, 0.0, this.angy-math.pi, 1.5)
|
||||
end
|
||||
|
||||
function this.show_hud()
|
||||
@ -427,9 +441,11 @@ function new_player(settings)
|
||||
(this.blz1*2+this.blz2)/3+0.5,
|
||||
-rotpos*0.01, -rotpos*0.004, 0.0, 0.1+0.01*math.sin(-rotpos*0.071))
|
||||
end
|
||||
--[[
|
||||
client.model_render_bone_local(mdl_test, mdl_test_bone,
|
||||
1-0.2, 600/800-0.2, 1.0,
|
||||
rotpos*0.01, rotpos*0.004, 0.0, 0.1)
|
||||
]]
|
||||
|
||||
-- TODO: not have this on all the time
|
||||
client.model_render_bone_local(mdl_spade, mdl_spade_bone,
|
||||
@ -445,11 +461,13 @@ function new_player(settings)
|
||||
1-0.60, -h/w+0.2+((this.tool == TOOL_NADE and 0.02*math.sin(rotpos*0.02)) or 0), 1.0,
|
||||
rotpos*0.01, 0.0, 0.0, 0.1*((this.tool == TOOL_NADE and 2.0) or 1.0))
|
||||
|
||||
this.render_tool()
|
||||
this.render()
|
||||
|
||||
if MODE_DEBUG_SHOWBOXES then
|
||||
client.model_render_bone_global(mdl_bbox,
|
||||
(this.crouching and mdl_bbox_bone2) or mdl_bbox_bone1,
|
||||
this.x, this.y, this.z, 0, 0, 0.0, 1)
|
||||
end
|
||||
|
||||
for i=1,players.max do
|
||||
local plr = players[i]
|
||||
@ -457,7 +475,7 @@ function new_player(settings)
|
||||
plr.render()
|
||||
if plr.team == this.team then
|
||||
local px,py
|
||||
local dx,dy,dz
|
||||
local dx,dy,dzNULL
|
||||
dx,dy,dz = plr.x-this.x,
|
||||
plr.y+plr.jerkoffs-this.y-this.jerkoffs-0.5,
|
||||
plr.z-this.z
|
||||
|
20
pkg/iceball/snowtest/main_client.lua
Normal file
20
pkg/iceball/snowtest/main_client.lua
Normal file
@ -0,0 +1,20 @@
|
||||
--[[
|
||||
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("[client] Testing the snow plugin!")
|
||||
dofile("pkg/base/main_client.lua")
|
||||
dofile("pkg/base/plug_snow.lua")
|
20
pkg/iceball/snowtest/main_server.lua
Normal file
20
pkg/iceball/snowtest/main_server.lua
Normal file
@ -0,0 +1,20 @@
|
||||
--[[
|
||||
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("[client] Testing the snow plugin!")
|
||||
dofile("pkg/base/main_client.lua")
|
||||
dofile("pkg/base/plug_snow.lua")
|
Loading…
x
Reference in New Issue
Block a user