diff --git a/common.h b/common.h index c209d9d..21e8c61 100644 --- a/common.h +++ b/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; diff --git a/docs/READ_THIS_FIRST.txt b/docs/READ_THIS_FIRST.txt index cbcf585..490a523 100644 --- a/docs/READ_THIS_FIRST.txt +++ b/docs/READ_THIS_FIRST.txt @@ -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. + diff --git a/docs/format_icemap.txt b/docs/format_icemap.txt new file mode 100644 index 0000000..0194ec2 --- /dev/null +++ b/docs/format_icemap.txt @@ -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. diff --git a/docs/modding_101.txt b/docs/modding_101.txt index 07153c1..c15e151 100644 --- a/docs/modding_101.txt +++ b/docs/modding_101.txt @@ -15,6 +15,8 @@ svsave///* 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//* + clsave///* Server only: - svsave//* + svsave///* + +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///whatever/* -- + pkg///whatever/name-X.XX.whatever + For instance, shotgun.kv6 would be: + pkg///kv6/shotgun-0.58.kv6 + OR, if converted to PMF: + pkg///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 diff --git a/docs/modding_lua.txt b/docs/modding_lua.txt index f8527fd..fd96e7c 100644 --- a/docs/modding_lua.txt +++ b/docs/modding_lua.txt @@ -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) @ diff --git a/docs/proto_main.txt b/docs/proto_main.txt index 11996b2..7545b5f 100644 --- a/docs/proto_main.txt +++ b/docs/proto_main.txt @@ -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 + + NOTE: will be IGNORED if the floodfill hits the bottom! - 0x05 pid: (S->C) + 0x0C pid x.fs y.fs z.fs ya.u8 xa.u8: (S->C) player spawn diff --git a/lua.c b/lua.c index b1bdac0..072feb5 100644 --- a/lua.c +++ b/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 - lua_newtable(lstate_client); - lua_setglobal(lstate_client, "client"); - lua_newtable(lstate_client); - lua_setglobal(lstate_client, "common"); + if(lstate_client != NULL) + { + lua_newtable(lstate_client); + lua_setglobal(lstate_client, "client"); + lua_newtable(lstate_client); + lua_setglobal(lstate_client, "common"); + } - lua_newtable(lstate_server); - lua_setglobal(lstate_server, "server"); - lua_newtable(lstate_server); - lua_setglobal(lstate_server, "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) { - printf("ERROR running server Lua: %s\n", lua_tostring(lstate_server, -1)); + 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); } - lua_pop(lstate_server, 1); - if(lua_pcall(lstate_client, 0, 0, 0) != 0) + if(lstate_client != NULL) { - printf("ERROR running client Lua: %s\n", lua_tostring(lstate_client, -1)); + 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); } - lua_pop(lstate_client, 1); return 0; } diff --git a/lua_camera.h b/lua_camera.h new file mode 100644 index 0000000..f6f6b54 --- /dev/null +++ b/lua_camera.h @@ -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 . +*/ + +// 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; +} diff --git a/lua_fetch.h b/lua_fetch.h new file mode 100644 index 0000000..5e22b47 --- /dev/null +++ b/lua_fetch.h @@ -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 . +*/ + +// 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; +} diff --git a/lua_image.h b/lua_image.h new file mode 100644 index 0000000..223f4b1 --- /dev/null +++ b/lua_image.h @@ -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 . +*/ + +// 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; +} diff --git a/lua_input.h b/lua_input.h new file mode 100644 index 0000000..992922e --- /dev/null +++ b/lua_input.h @@ -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 . +*/ + +// 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; +} diff --git a/lua_map.h b/lua_map.h new file mode 100644 index 0000000..44e3672 --- /dev/null +++ b/lua_map.h @@ -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 . +*/ + +// 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; +} diff --git a/lua_model.h b/lua_model.h new file mode 100644 index 0000000..5447beb --- /dev/null +++ b/lua_model.h @@ -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 . +*/ + +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; +} diff --git a/main.c b/main.c index f4df006..2e24973 100644 --- a/main.c +++ b/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,7 +132,8 @@ int update_client(void) lua_pop(lstate_client, 1); return 1; } - sec_wait += lua_tonumber(lstate_client, -1); + if(!(boot_mode & 2)) + sec_wait += lua_tonumber(lstate_client, -1); lua_pop(lstate_client, 1); // redraw scene if necessary @@ -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]); } diff --git a/main.make b/main.make index badf04a..aa1a210 100644 --- a/main.make +++ b/main.make @@ -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) $< diff --git a/opencmd.bat b/opencmd.bat new file mode 100644 index 0000000..d0d0d2a --- /dev/null +++ b/opencmd.bat @@ -0,0 +1,2 @@ +@echo off +command diff --git a/path.c b/path.c new file mode 100644 index 0000000..dafd274 --- /dev/null +++ b/path.c @@ -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 . +*/ + +#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; +} diff --git a/pkg/base/common.lua b/pkg/base/common.lua new file mode 100644 index 0000000..bec3fbb --- /dev/null +++ b/pkg/base/common.lua @@ -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 . +]] + +-- 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 diff --git a/pkg/base/lib_gui.lua b/pkg/base/lib_gui.lua index aa7235b..c802882 100644 --- a/pkg/base/lib_gui.lua +++ b/pkg/base/lib_gui.lua @@ -15,10 +15,10 @@ along with Ice Lua Components. If not, see . ]] -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! diff --git a/pkg/base/main_client.lua b/pkg/base/main_client.lua index 48f8ff1..31e6c39 100644 --- a/pkg/base/main_client.lua +++ b/pkg/base/main_client.lua @@ -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") diff --git a/pkg/base/main_server.lua b/pkg/base/main_server.lua index 04a9820..00b4f03 100644 --- a/pkg/base/main_server.lua +++ b/pkg/base/main_server.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) diff --git a/pkg/base/obj_player.lua b/pkg/base/obj_player.lua index 3690cd7..75ccb16 100644 --- a/pkg/base/obj_player.lua +++ b/pkg/base/obj_player.lua @@ -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 - - 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) + 0.0, 0-math.pi/4+swing, this.angy-math.pi, 2.0) - 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() - 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) + 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 diff --git a/pkg/iceball/snowtest/main_client.lua b/pkg/iceball/snowtest/main_client.lua new file mode 100644 index 0000000..ca9ed28 --- /dev/null +++ b/pkg/iceball/snowtest/main_client.lua @@ -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 . +]] + +print("[client] Testing the snow plugin!") +dofile("pkg/base/main_client.lua") +dofile("pkg/base/plug_snow.lua") diff --git a/pkg/iceball/snowtest/main_server.lua b/pkg/iceball/snowtest/main_server.lua new file mode 100644 index 0000000..ca9ed28 --- /dev/null +++ b/pkg/iceball/snowtest/main_server.lua @@ -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 . +]] + +print("[client] Testing the snow plugin!") +dofile("pkg/base/main_client.lua") +dofile("pkg/base/plug_snow.lua")