bunch of arch reworking; scripts take arguments now; arms/legs dangle too

This commit is contained in:
Ben Russell (300178622) 2012-11-26 17:06:30 +13:00
parent 6d2ee44e0d
commit cc0461a9ca
24 changed files with 1456 additions and 970 deletions

View File

@ -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;

View File

@ -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
View 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.

View File

@ -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

View File

@ -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) @

View File

@ -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
View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -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]);
}

View File

@ -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
View File

@ -0,0 +1,2 @@
@echo off
command

32
path.c Normal file
View 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
View 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

View File

@ -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!

View File

@ -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")

View File

@ -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)

View File

@ -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

View 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")

View 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")