From 567e9f112b5d16ac86ff54b96fc1250acdfecfff Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 24 Jan 2012 04:24:14 +0000 Subject: [PATCH] added DP_QC_ENTITYSTRING builtins. mvd playback fixes/cleanups r_fb_models more closely matches ezquake. readded str[i] support. fixed char constants (outside of strings). string table compression no longer affects distinction between "" and string_null. multiplayer savedgame fixes. don't bugilly change hexen2's playerclass on loadgame, and preserve the STR_foo globals which are not marked for saving. fix small bug on player renames. added a temp debug print to try to catch the issue onemanclan is having. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3961 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 247 +------- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 11 +- engine/client/cl_parse.c | 23 +- engine/client/cl_pred.c | 43 +- engine/client/m_options.c | 16 + engine/client/pr_csqc.c | 32 +- engine/client/pr_menu.c | 91 +-- engine/client/renderer.c | 2 +- engine/client/sbar.c | 2 - engine/client/valid.c | 8 +- engine/client/view.c | 4 +- engine/common/common.h | 2 +- engine/common/fs.c | 2 +- engine/common/pr_bgcmd.c | 124 +++- engine/common/pr_common.h | 6 + .../droid/src/com/fteqw/FTEDroidActivity.java | 596 +++++++++--------- engine/gl/gl_alias.c | 9 +- engine/gl/gl_model.c | 12 + engine/gl/gl_model.h | 1 + engine/qclib/pr_comp.h | 4 +- engine/qclib/pr_edict.c | 30 + engine/qclib/progsint.h | 1 + engine/qclib/qcc_pr_comp.c | 17 +- engine/qclib/qcc_pr_lex.c | 1 + engine/qclib/qccmain.c | 14 +- engine/server/pr_cmds.c | 16 +- engine/server/savegame.c | 61 +- engine/server/sv_main.c | 14 +- engine/server/sv_send.c | 12 +- engine/server/sv_user.c | 1 + 31 files changed, 714 insertions(+), 690 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index b0ff0b031..2a15405f8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1914,7 +1914,7 @@ void CL_TransitionEntities (void) vec3_t move; lerpents_t *le; player_state_t *pnew, *pold; - if (!cl_lerp_players.ival) + if (!cl_lerp_players.ival && !(cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)) { newf = newff = oldf = cl.parsecount; newf&=UPDATE_MASK; @@ -2461,6 +2461,29 @@ CL_ParsePlayerinfo extern int parsecountmod, oldparsecountmod; extern double parsecounttime; int lastplayerinfo; + +void CL_ParseClientdata (void); +void CL_MVDUpdateSpectator(void) +{ + player_state_t *self, *oldself; + int s; + for (s = 0; s < cl.splitclients; s++) + { + self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[s]]; + oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[s]]; +// cl.frames[cl.parsecount & UPDATE_MASK].senttime = cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].senttime; + +// self->messagenum = cl.parsecount; + +// VectorCopy(oldself->origin, self->origin); +// VectorCopy(oldself->velocity, self->velocity); +// VectorCopy(oldself->viewangles, self->viewangles); + } + + CL_ParseClientdata(); +} + + void CL_ParsePlayerinfo (void) { int msec; @@ -2470,7 +2493,7 @@ void CL_ParsePlayerinfo (void) int num; int i; int newf; - vec3_t org; + vec3_t org, dist; lastplayerinfo = num = MSG_ReadByte (); if (num >= MAX_CLIENTS) @@ -2522,6 +2545,10 @@ void CL_ParsePlayerinfo (void) state->origin[i] = MSG_ReadCoord (); } + VectorSubtract(state->origin, prevstate->origin, dist); + VectorScale(dist, 1/(cl.frames[parsecountmod].packet_entities.servertime - cl.frames[oldparsecountmod].packet_entities.servertime), state->velocity); + VectorCopy (state->origin, state->predorigin); + for (i = 0; i < 3; i++) { if (flags & (DF_ANGLES << i)) @@ -3096,7 +3123,7 @@ void CL_LinkPlayers (void) if (pnum < cl.splitclients) { //this is a local player } - else if (cl_lerp_players.ival) + else if (cl_lerp_players.ival || (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV)) { lerpents_t *le = &cl.lerpplayers[j]; VectorCopy (le->origin, ent->origin); @@ -3518,223 +3545,9 @@ void CL_EmitEntities (void) -void CL_ParseClientdata (void); -/* -void MVD_Interpolate(void) -{ - player_state_t *self, *oldself; - - CL_ParseClientdata(); - - self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[0]]; - oldself = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK].playerstate[cl.playernum[0]]; - self->messagenum = cl.parsecount; - VectorCopy(oldself->origin, self->origin); - VectorCopy(oldself->velocity, self->velocity); - VectorCopy(oldself->viewangles, self->viewangles); - - - cls.netchan.outgoing_sequence = cl.parsecount+1; -} - -*/ - -int mvd_fixangle; - -static float MVD_AdjustAngle(float current, float ideal, float fraction) { - float move; - - move = ideal - current; - if (move >= 180) - move -= 360; - else if (move <= -180) - move += 360; - - return current + fraction * move; -} - -extern float nextdemotime; -extern float olddemotime; - -static void MVD_InitInterpolation(void) -{ - player_state_t *state, *oldstate; - int i, tracknum; - frame_t *frame, *oldframe; - vec3_t dist; - struct predicted_player *pplayer; - int s; - -#define ISDEAD(i) ( (i) >= 41 && (i) <= 102 ) - - if (!cl.validsequence) - return; - -// if (nextdemotime <= olddemotime) -// return; - - frame = &cl.frames[cl.parsecount & UPDATE_MASK]; - oldframe = &cl.frames[(cl.parsecount-1) & UPDATE_MASK]; - - // clients - for (i = 0; i < MAX_CLIENTS; i++) - { - pplayer = &predicted_players[i]; - state = &frame->playerstate[i]; - oldstate = &oldframe->playerstate[i]; - - if (pplayer->predict) - { - VectorCopy(pplayer->oldo, oldstate->origin); - VectorCopy(pplayer->olda, oldstate->command.angles); - VectorCopy(pplayer->oldv, oldstate->velocity); - } - - pplayer->predict = false; - - tracknum = spec_track[0]; - if ((mvd_fixangle & 1) << i) - { - if (i == tracknum) - { - state->command.angles[0] = (state->viewangles[0] = cl.viewangles[0][0])*65535/360; - state->command.angles[1] = (state->viewangles[1] = cl.viewangles[0][1])*65535/360; - state->command.angles[2] = (state->viewangles[2] = cl.viewangles[0][2])*65535/360; - } - - // no angle interpolation - VectorCopy(state->command.angles, oldstate->command.angles); - - mvd_fixangle &= ~(1 << i); - } - - // we dont interpolate ourself if we are spectating - for (s = 0; s < cl.splitclients; s++) - { - if (i == cl.playernum[s] && cl.spectator) - break; - } - if (s != cl.splitclients) - continue; - - memset(state->velocity, 0, sizeof(state->velocity)); - - if (state->messagenum != cl.parsecount) - continue; // not present this frame - - if (oldstate->messagenum != cl.oldparsecount || !oldstate->messagenum) - continue; // not present last frame - - if (!ISDEAD(state->frame) && ISDEAD(oldstate->frame)) - continue; - - VectorSubtract(state->origin, oldstate->origin, dist); - if (DotProduct(dist, dist) > 22500) - continue; - - VectorScale(dist, 1 / (nextdemotime - olddemotime), pplayer->oldv); - - VectorCopy(state->origin, pplayer->oldo); - VectorCopy(state->command.angles, pplayer->olda); - - pplayer->oldstate = oldstate; - pplayer->predict = true; - } -/* - // nails - for (i = 0; i < cl_num_projectiles; i++) - { - if (!cl.int_projectiles[i].interpolate) - continue; - - VectorCopy(cl.int_projectiles[i].origin, cl_projectiles[i].origin); - } -*/ -} - -void MVD_Interpolate(void) -{ - int i, j; - float f; - frame_t *frame, *oldframe; - player_state_t *state, *oldstate, *self, *oldself; - entity_state_t *oldents; - struct predicted_player *pplayer; - static float old; - extern float demtime; - int s; - - for (s = 0; s < cl.splitclients; s++) - { - self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[s]]; - oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[s]]; - - self->messagenum = cl.parsecount; - - VectorCopy(oldself->origin, self->origin); - VectorCopy(oldself->velocity, self->velocity); - VectorCopy(oldself->viewangles, self->viewangles); - } - - if (old != nextdemotime) - { - old = nextdemotime; - MVD_InitInterpolation(); - } - - CL_ParseClientdata(); - - cls.netchan.outgoing_sequence = cl.parsecount + 1; - - if (!cl.validsequence) - return; - - if (nextdemotime <= olddemotime) - return; - - frame = &cl.frames[cl.validsequence & UPDATE_MASK]; - oldframe = &cl.frames[cl.oldvalidsequence & UPDATE_MASK]; - oldents = oldframe->packet_entities.entities; - - f = (demtime - olddemotime) / (nextdemotime - olddemotime); - f = bound(0, f, 1); - - // interpolate nails -/* for (i = 0; i < cl_num_projectiles; i++) - { - if (!cl.int_projectiles[i].interpolate) - continue; - - for (j = 0; j < 3; j++) - { - cl_projectiles[i].origin[j] = cl_oldprojectiles[cl.int_projectiles[i].oldindex].origin[j] + - f * (cl.int_projectiles[i].origin[j] - cl_oldprojectiles[cl.int_projectiles[i].oldindex].origin[j]); - } - } -*/ - - // interpolate clients - for (i = 0; i < MAX_CLIENTS; i++) - { - pplayer = &predicted_players[i]; - state = &frame->playerstate[i]; - oldstate = &oldframe->playerstate[i]; - - if (pplayer->predict) - { - for (j = 0; j < 3; j++) - { - state->viewangles[j] = MVD_AdjustAngle(oldstate->command.angles[j]/65535.0f*360, pplayer->olda[j]/65535.0f*360, f); - state->origin[j] = oldstate->origin[j] + f * (pplayer->oldo[j] - oldstate->origin[j]); - state->velocity[j] = oldstate->velocity[j] + f * (pplayer->oldv[j] - oldstate->velocity[j]); - } - } - } -} void CL_ClearPredict(void) { memset(predicted_players, 0, sizeof(predicted_players)); - mvd_fixangle = 0; } diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 296934cf6..e3101a9e0 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1361,7 +1361,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) extern cvar_t cl_splitscreen; i = cls.netchan.outgoing_sequence & UPDATE_MASK; cl.frames[i].senttime = realtime; // we haven't gotten a reply yet - cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet +// cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet if (cl.splitclients > cl_splitscreen.ival+1) { diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f9f8110f5..0ebd4fb72 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -75,7 +75,7 @@ cvar_t m_yaw = CVARF("m_yaw","0.022", CVAR_ARCHIVE); cvar_t m_forward = CVARF("m_forward","1", CVAR_ARCHIVE); cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE); -cvar_t cl_lerp_players = CVARD("cl_lerp_players", "1", "Set this to make other players smoother, though it may increase effective latency. Affects only QuakeWorld."); +cvar_t cl_lerp_players = CVARD("cl_lerp_players", "0", "Set this to make other players smoother, though it may increase effective latency. Affects only QuakeWorld."); cvar_t cl_predict_players = CVARD("cl_predict_players", "1", "Clear this cvar to see ents exactly how they are on the server."); cvar_t cl_solid_players = CVAR("cl_solid_players", "1"); cvar_t cl_noblink = CVARD("cl_noblink", "0", "Disable the ^^b text blinking feature."); @@ -170,6 +170,7 @@ cvar_t ruleset_allow_modified_eyes = SCVAR("ruleset_allow_modified_eyes", "0"); cvar_t ruleset_allow_sensative_texture_replacements = SCVAR("ruleset_allow_sensative_texture_replacements", "1"); cvar_t ruleset_allow_localvolume = SCVAR("ruleset_allow_localvolume", "1"); cvar_t ruleset_allow_shaders = SCVARF("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM); +cvar_t ruleset_allow_fbmodels = SCVARF("ruleset_allow_fbmodels", "1", CVAR_SHADERSYSTEM); extern cvar_t cl_hightrack; extern cvar_t vid_renderer; @@ -2706,6 +2707,8 @@ void CLNQ_ConnectionlessPacket(void) } #endif +void CL_MVDUpdateSpectator (void); + /* ================= CL_ReadPackets @@ -2810,6 +2813,7 @@ void CL_ReadPackets (void) case CP_QUAKEWORLD: if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { + player_state_t *n,*o; MSG_BeginReading(cls.netchan.netprim); cls.netchan.last_received = realtime; cls.netchan.outgoing_sequence = cls.netchan.incoming_sequence; @@ -2851,7 +2855,9 @@ void CL_ReadPackets (void) } if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) - MVD_Interpolate(); + { + CL_MVDUpdateSpectator(); + } } //============================================================================= @@ -3273,6 +3279,7 @@ void CL_Init (void) Cvar_Register (&ruleset_allow_sensative_texture_replacements, cl_controlgroup); Cvar_Register (&ruleset_allow_localvolume, cl_controlgroup); Cvar_Register (&ruleset_allow_shaders, cl_controlgroup); + Cvar_Register (&ruleset_allow_fbmodels, cl_controlgroup); Cvar_Register (&qtvcl_forceversion1, cl_controlgroup); Cvar_Register (&qtvcl_eztvextensions, cl_controlgroup); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 35464d077..02a330dbb 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2277,15 +2277,18 @@ void CLQW_ParseServerData (void) if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { - int i; + int i,j; MSG_ReadFloat(); - cl.playernum[0] = MAX_CLIENTS; - cl.playernum[1] = MAX_CLIENTS+1; - cl.playernum[2] = MAX_CLIENTS+2; - cl.playernum[3] = MAX_CLIENTS+3; + for (j = 0; j < MAX_SPLITS; j++) + { + cl.playernum[j] = MAX_CLIENTS + j; + for (i = 0; i < UPDATE_BACKUP; i++) + { + cl.frames[i].playerstate[cl.playernum[j]].pm_type = PM_SPECTATOR; + cl.frames[i].playerstate[cl.playernum[j]].messagenum = 1; + } + } cl.spectator = true; - for (i = 0; i < UPDATE_BACKUP; i++) - cl.frames[i].playerstate[cl.playernum[0]].pm_type = PM_SPECTATOR; cl.splitclients = 1; } @@ -3695,7 +3698,10 @@ void CL_ParseClientdata (void) i = cls.netchan.incoming_acknowledged; if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) + { cl.oldparsecount = i - 1; + oldparsecountmod = cl.oldparsecount & UPDATE_MASK; + } cl.parsecount = i; i &= UPDATE_MASK; parsecountmod = i; @@ -3704,7 +3710,8 @@ void CL_ParseClientdata (void) frame->senttime = realtime - host_frametime; parsecounttime = cl.frames[i].senttime; - frame->receivedtime = (cl.gametimemark - cl.oldgametimemark)*20; + frame->receivedtime = realtime; + //(cl.gametimemark - cl.oldgametimemark)*20; // calculate latency latency = frame->receivedtime - frame->senttime; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index db447f404..f141633e7 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -762,7 +762,7 @@ void CL_PredictMovePNum (int pnum) float f; frame_t *from, *to = NULL; int oldphysent; - vec3_t lrp; + vec3_t lrp, lrpv; //these are to make svc_viewentity work better float *vel; @@ -881,7 +881,7 @@ fixedorg: if (Cam_TrackNum(pnum)>=0 && CL_MayLerp()) { float f; - if (cl_lerp_players.ival) + if (cl_lerp_players.ival && (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV)) { lerpents_t *le = &cl.lerpplayers[spec_track[pnum]]; org = le->origin; @@ -911,29 +911,46 @@ fixedorg: lrp[i] = to->playerstate[cl.playernum[pnum]].origin[i] + f * (from->playerstate[cl.playernum[pnum]].origin[i] - to->playerstate[cl.playernum[pnum]].origin[i]); + lrpv[i] = to->playerstate[spec_track[pnum]].velocity[i] + + f * (from->playerstate[spec_track[pnum]].velocity[i] - to->playerstate[spec_track[pnum]].velocity[i]); + cl.simangles[pnum][i] = LerpAngles16(to->playerstate[spec_track[pnum]].command.angles[i], from->playerstate[spec_track[pnum]].command.angles[i], f)*360.0f/65535; } org = lrp; + vel = lrpv; goto fixedorg; } else { - for (i=1 ; iplayerstate->pm_type = PM_FLY; - CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] - , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + to = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK]; + to->playerstate->pm_type = PM_SPECTATOR; - cl.onground[pnum] = pmove.onground; + VectorCopy (cl.simvel[pnum], from->playerstate[cl.playernum[pnum]].velocity); + VectorCopy (cl.simorg[pnum], from->playerstate[cl.playernum[pnum]].origin); - if (to->senttime >= realtime) - break; - from = to; + CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]], &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + } + else + { + for (i=1 ; iplayerstate->pm_type = PM_FLY; + CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] + , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + + cl.onground[pnum] = pmove.onground; + + if (to->senttime >= realtime) + break; + from = to; + } } if (independantphysics[pnum].msec) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 0c5b2e942..770d2ced7 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -899,6 +899,21 @@ void M_Menu_Lighting_f (void) NULL }; + static const char *fb_models_opts[] = + { + "Disabled", + "Entire model", + "If textured", + NULL + }; + static const char *fb_models_values[] = + { + "0", + "1", + "2", + NULL + }; + int y; menu_t *menu = M_Options_Title(&y, sizeof(lightingmenuinfo_t)); int lightselect, dlightselect; @@ -955,6 +970,7 @@ void M_Menu_Lighting_f (void) MB_SLIDER("Blob Shadows", r_shadows, 0, 1, 0.05, "Small blobs underneath monsters and players, to add depth to the scene without excessive rendering."), MB_SLIDER("Stains", r_stains, 0, 1, 0.05, "Allows discolouration of world surfaces, commonly used for blood trails."), MB_CHECKBOXCVARTIP("No Light Direction", r_nolightdir, 0, "Disables shading calculations for uniform light levels on models from all directions."), + MB_COMBOCVAR("Model Fullbrights", r_fb_models, fb_models_opts, fb_models_values, "Affects loading of fullbrights on models/polymeshes."), MB_END() }; MC_AddBulk(menu, bulk, 16, 216, y); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 5a9f38a6d..d9bd89a2b 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -4446,35 +4446,35 @@ static struct { #endif //DP_QC_CRC16 - {"crc16", PF_crc16, 494}, // #494 float(float caseinsensitive, string s, ...) crc16 + {"crc16", PF_crc16, 494}, // #494 float(float caseinsensitive, string s, ...) crc16 //DP_QC_CVAR_TYPE - {"cvar_type", PF_cvar_type, 495}, // #495 float(string name) cvar_type + {"cvar_type", PF_cvar_type, 495}, // #495 float(string name) cvar_type //DP_QC_ENTITYDATA - {"numentityfields", PF_numentityfields, 496}, // #496 float() numentityfields - {"entityfieldname", PF_entityfieldname, 497}, // #497 string(float fieldnum) entityfieldname - {"entityfieldtype", PF_entityfieldtype, 498}, // #498 float(float fieldnum) entityfieldtype - {"getentityfieldstring",PF_getentityfieldstring, 499}, // #499 string(float fieldnum, entity ent) getentityfieldstring + {"numentityfields", PF_numentityfields, 496}, // #496 float() numentityfields + {"entityfieldname", PF_entityfieldname, 497}, // #497 string(float fieldnum) entityfieldname + {"entityfieldtype", PF_entityfieldtype, 498}, // #498 float(float fieldnum) entityfieldtype + {"getentityfieldstring",PF_getentityfieldstring, 499}, // #499 string(float fieldnum, entity ent) getentityfieldstring {"putentityfieldstring",PF_putentityfieldstring, 500}, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring //DP_SV_WRITEPICTURE - {"WritePicture", PF_ReadPicture, 501}, // #501 void(float to, string s, float sz) WritePicture + {"WritePicture", PF_ReadPicture, 501}, // #501 void(float to, string s, float sz) WritePicture //no 502 documented //DP_QC_WHICHPACK - {"whichpack", PF_whichpack, 503}, // #503 string(string filename) whichpack + {"whichpack", PF_whichpack, 503}, // #503 string(string filename) whichpack //DP_QC_URI_ESCAPE - {"uri_escape", PF_uri_escape, 510}, // #510 string(string in) uri_escape - {"uri_unescape", PF_uri_unescape, 511}, // #511 string(string in) uri_unescape = #511; + {"uri_escape", PF_uri_escape, 510}, // #510 string(string in) uri_escape + {"uri_unescape", PF_uri_unescape, 511}, // #511 string(string in) uri_unescape = #511; //DP_QC_NUM_FOR_EDICT - {"num_for_edict", PF_num_for_edict, 512}, // #512 float(entity ent) num_for_edict + {"num_for_edict", PF_num_for_edict, 512}, // #512 float(entity ent) num_for_edict //DP_QC_URI_GET - {"uri_get", PF_uri_get, 513}, // #513 float(string uril, float id) uri_get + {"uri_get", PF_uri_get, 513}, // #513 float(string uril, float id) uri_get {"tokenize_console", PF_tokenize_console, 514}, {"argv_start_index", PF_argv_start_index, 515}, @@ -4487,6 +4487,14 @@ static struct { {"keynumtostring", PF_cl_keynumtostring, 520}, {"findkeysforcommand", PF_cl_findkeysforcommand, 521}, + {"loadfromdata", PF_loadfromdata, 529}, + {"loadfromfile", PF_loadfromfile, 530}, + + {"callfunction", PF_callfunction, 605}, + {"writetofile", PF_writetofile, 606}, + {"isfunction", PF_isfunction, 607}, + {"parseentitydata", PF_parseentitydata, 608}, + {"sprintf", PF_sprintf, 627}, {NULL} diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index ba87a0352..8cf4c1f99 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -689,95 +689,6 @@ cvar_t pr_menuqc_coreonerror = SCVAR("pr_menuqc_coreonerror", "1"); //new generic functions. -//float isfunction(string function_name) = #607; -void QCBUILTIN PF_isfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *name = PR_GetStringOfs(prinst, OFS_PARM0); - G_FLOAT(OFS_RETURN) = !!PR_FindFunction(prinst, name, PR_CURRENT); -} - -//void callfunction(...) = #605; -void QCBUILTIN PF_callfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *name; - func_t f; - if (*prinst->callargc < 1) - PR_BIError(prinst, "callfunction needs at least one argument\n"); - name = PR_GetStringOfs(prinst, OFS_PARM0+(*prinst->callargc-1)*3); - f = PR_FindFunction(prinst, name, PR_CURRENT); - if (f) - PR_ExecuteProgram(prinst, f); -} - -//void loadfromfile(string file) = #69; -void QCBUILTIN PF_loadfromfile (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *filename = PR_GetStringOfs(prinst, OFS_PARM0); - char *file = COM_LoadTempFile(filename); - - int size; - - if (!file) - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - while(prinst->restoreent(prinst, file, &size, NULL)) - { - file += size; - } - - G_FLOAT(OFS_RETURN) = 0; -} - -void QCBUILTIN PF_loadfromdata (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *file = PR_GetStringOfs(prinst, OFS_PARM0); - - int size; - - if (!*file) - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - while(prinst->restoreent(prinst, file, &size, NULL)) - { - file += size; - } - - G_FLOAT(OFS_RETURN) = 0; -} - -void QCBUILTIN PF_parseentitydata(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - void *ed = G_EDICT(prinst, OFS_PARM0); - char *file = PR_GetStringOfs(prinst, OFS_PARM1); - - int size; - - if (!*file) - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - if (!prinst->restoreent(prinst, file, &size, ed)) - Con_Printf("parseentitydata: missing opening data\n"); - else - { - file += size; - while(*file < ' ' && *file) - file++; - if (*file) - Con_Printf("parseentitydata: too much data\n"); - } - - G_FLOAT(OFS_RETURN) = 0; -} - void QCBUILTIN PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int a = G_FLOAT(OFS_PARM0); @@ -1728,7 +1639,7 @@ builtin_t menu_builtins[] = { PF_cl_setmousetarget, PF_cl_getmousetarget, PF_callfunction, - skip1 //void writetofile(float fhandle, entity ent) = #606; + PF_writetofile, //void writetofile(float fhandle, entity ent) = #606; PF_isfunction, PF_cl_getresolution, PF_cl_keynumtostring, diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 4998c74d8..a1cc04993 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -87,7 +87,7 @@ cvar_t r_fastskycolour = CVARF ("r_fastskycolour", "0", cvar_t r_fb_bmodels = CVARAF("r_fb_bmodels", "1", "gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_fb_models = CVARAF ("r_fb_models", "1", - "gl_fb_models", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); + "gl_fb_models", CVAR_SEMICHEAT); cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_coronas = SCVARF ("r_coronas", "0", diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 639006306..89feba682 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -3280,8 +3280,6 @@ Sbar_FinaleOverlay */ void Sbar_FinaleOverlay (void) { - mpic_t *pic; - #ifdef VM_UI if (UI_DrawFinale()>0) return; diff --git a/engine/client/valid.c b/engine/client/valid.c index d67517ba6..e5ad13280 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -305,7 +305,7 @@ static void Validation_Server(void) static void Validation_Skins(void) { - extern cvar_t r_fullbrightSkins, r_fb_models; + extern cvar_t r_fullbrightSkins, r_fb_models, ruleset_allow_fbmodels; int percent = r_fullbrightSkins.value*100; if (!allow_f_skins.ival) @@ -319,7 +319,9 @@ static void Validation_Skins(void) if (percent > cls.allow_fbskins*100) percent = cls.allow_fbskins*100; if (percent) - Cbuf_AddText(va("say all player skins %i%% fullbright%s\n", percent, r_fb_models.value?" (plus luma)":""), RESTRICT_LOCAL); + Cbuf_AddText(va("say all player skins %i%% fullbright%s\n", percent, (r_fb_models.ival == 1 && ruleset_allow_fbmodels.ival)?" (non-player 100%%)":(r_fb_models.value?" (plus luma)":"")), RESTRICT_LOCAL); + else if (r_fb_models.ival == 1 && ruleset_allow_fbmodels.ival) + Cbuf_AddText("say non-player entities glow in the dark like a bright big cheat\n", RESTRICT_LOCAL); else if (r_fb_models.ival) Cbuf_AddText("say luma textures only\n", RESTRICT_LOCAL); else @@ -390,6 +392,7 @@ rulesetrule_t rulesetrules_strict[] = { {"ruleset_allow_modified_eyes", "0"}, {"ruleset_allow_sensative_texture_replacements", "0"}, {"ruleset_allow_localvolume", "0"}, + {"ruleset_allow_fbmodels", "0"}, {"tp_disputablemacros", "0"}, {"cl_instantrotate", "0"}, {"v_projectionmode", "0"}, /*no extended fovs*/ @@ -407,6 +410,7 @@ rulesetrule_t rulesetrules_nqr[] = { {"ruleset_allow_sensative_texture_replacements", "0"}, {"ruleset_allow_localvolume", "0"}, {"ruleset_allow_shaders", "0"}, + {"ruleset_allow_fbmodels", "0"}, {"r_vertexlight", "0"}, {"v_projectionmode", "0"}, {NULL} diff --git a/engine/client/view.c b/engine/client/view.c index b63d668d2..fb68a38dd 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1283,8 +1283,8 @@ void R_DrawNameTags(void) #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { -// void GL_Set2D (void); -// GL_Set2D(false); + void GL_Set2D (qboolean flipped); + GL_Set2D(false); } #endif diff --git a/engine/common/common.h b/engine/common/common.h index e2234665e..79291a2a4 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -320,7 +320,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation struct vfsfile_s *FS_OpenReadLocation(flocation_t *location); char *FS_WhichPackForLocation(flocation_t *loc); -qboolean FS_GetPackageDownloadable(char *package); +qboolean FS_GetPackageDownloadable(const char *package); char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackNames(char *buffer, int buffersize, int referencedonly, qboolean ext); void FS_ReferenceControl(unsigned int refflag, unsigned int resetflags); diff --git a/engine/common/fs.c b/engine/common/fs.c index dc3aa3ff5..5bbc1219d 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -587,7 +587,7 @@ char *FS_WhichPackForLocation(flocation_t *loc) } /*requires extension*/ -qboolean FS_GetPackageDownloadable(char *package) +qboolean FS_GetPackageDownloadable(const char *package) { searchpath_t *search; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 292d5d223..c78dbd6d7 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -963,11 +963,8 @@ void QCBUILTIN PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_TSTRING(pr_string_temp); } -void QCBUILTIN PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +static void PF_fwrite (progfuncs_t *prinst, int fnum, char *msg, int len) { - int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - char *msg = PF_VarString(prinst, 1, pr_globals); - int len = strlen(msg); if (fnum < 0 || fnum >= MAX_QC_FILES) { Con_Printf("PF_fgets: File out of range\n"); @@ -1010,6 +1007,15 @@ void QCBUILTIN PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } +void QCBUILTIN PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; + char *msg = PF_VarString(prinst, 1, pr_globals); + int len = strlen(msg); + + PF_fwrite (prinst, fnum, msg, len); +} + void PF_fcloseall (progfuncs_t *prinst) { int i; @@ -1235,6 +1241,116 @@ void PR_fclose_progs (progfuncs_t *prinst) //File access //////////////////////////////////////////////////// +//reflection + +//float isfunction(string function_name) +void QCBUILTIN PF_isfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name = PR_GetStringOfs(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = !!PR_FindFunction(prinst, name, PR_CURRENT); +} + +//void callfunction(...) +void QCBUILTIN PF_callfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name; + func_t f; + if (*prinst->callargc < 1) + PR_BIError(prinst, "callfunction needs at least one argument\n"); + name = PR_GetStringOfs(prinst, OFS_PARM0+(*prinst->callargc-1)*3); + *prinst->callargc -= 1; + f = PR_FindFunction(prinst, name, PR_CURRENT); + if (f) + PR_ExecuteProgram(prinst, f); +} + +//void loadfromfile(string file) +void QCBUILTIN PF_loadfromfile (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *filename = PR_GetStringOfs(prinst, OFS_PARM0); + char *file = COM_LoadTempFile(filename); + + int size; + + if (!file) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + while(prinst->restoreent(prinst, file, &size, NULL)) + { + file += size; + } + + G_FLOAT(OFS_RETURN) = 0; +} + +void QCBUILTIN PF_writetofile(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int fnum = G_FLOAT(OFS_PARM0); + void *ed = G_EDICT(prinst, OFS_PARM1); + + char buffer[65536]; + char *entstr; + int buflen; + + buflen = sizeof(buffer); + entstr = prinst->saveent(prinst, buffer, &buflen, ed); //will save just one entities vars + if (entstr) + { + PF_fwrite (prinst, fnum, entstr, buflen); + } +} + +void QCBUILTIN PF_loadfromdata (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *file = PR_GetStringOfs(prinst, OFS_PARM0); + + int size; + + if (!*file) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + while(prinst->restoreent(prinst, file, &size, NULL)) + { + file += size; + } + + G_FLOAT(OFS_RETURN) = 0; +} + +void QCBUILTIN PF_parseentitydata(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + void *ed = G_EDICT(prinst, OFS_PARM0); + char *file = PR_GetStringOfs(prinst, OFS_PARM1); + + int size; + + if (!*file) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + if (!prinst->restoreent(prinst, file, &size, ed)) + Con_Printf("parseentitydata: missing opening data\n"); + else + { + file += size; + while(*file < ' ' && *file) + file++; + if (*file) + Con_Printf("parseentitydata: too much data\n"); + } + + G_FLOAT(OFS_RETURN) = 0; +} +//reflection +//////////////////////////////////////////////////// //Entities void QCBUILTIN PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 0d58dc449..d5b59afb7 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -159,6 +159,12 @@ void QCBUILTIN PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_glo void QCBUILTIN PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_isfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_callfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_writetofile(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_loadfromfile (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_loadfromdata (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_parseentitydata(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_crc16 (progfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/droid/src/com/fteqw/FTEDroidActivity.java b/engine/droid/src/com/fteqw/FTEDroidActivity.java index b28171476..f0942f0d6 100644 --- a/engine/droid/src/com/fteqw/FTEDroidActivity.java +++ b/engine/droid/src/com/fteqw/FTEDroidActivity.java @@ -1,284 +1,312 @@ -package com.fteqw; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import android.app.Activity; -import android.content.Context; -import android.os.Bundle; -import android.view.Window; -import android.view.WindowManager; - -import android.opengl.GLSurfaceView; -import android.view.KeyEvent; -import android.view.MotionEvent; - -import android.hardware.SensorManager; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; - -import android.media.AudioFormat; -import android.media.AudioManager; -import android.media.AudioTrack; - -public class FTEDroidActivity extends Activity -{ - private SensorManager sensorman; - private Sensor sensoracc; - private FTEView view; - - private class FTERenderer implements GLSurfaceView.Renderer - { - private boolean inited; - @Override - public void onDrawFrame(GL10 gl) - { - if (inited == true) - { - FTEDroidEngine.frame(); - } - } - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) - { - FTEDroidEngine.init(width, height); - inited = true; - } - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) - { - } - } - private class FTEView extends GLSurfaceView implements SensorEventListener - { - private final FTERenderer rndr; - - private byte[] audbuf; - private AudioTrack at; - - private void audioInit() - { - final int notifframes = 2048; - if (at != null) - at.stop(); - int sspeed = 11025; - int speakers = 1; - int sz = 4*AudioTrack.getMinBufferSize(sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT); - if (sz < notifframes*2) - sz = notifframes*2; - - at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT, sz, AudioTrack.MODE_STREAM); - final int framesz = 2; /*mono 16bit*/ - audbuf = new byte[notifframes*framesz]; - - at.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() - { - @Override - public void onMarkerReached(AudioTrack track) - { - } - @Override - public void onPeriodicNotification(AudioTrack track) - { - int avail = FTEDroidEngine.paintaudio(audbuf, audbuf.length); - at.write(audbuf, 0, notifframes*framesz); - } - }); - at.setPositionNotificationPeriod(notifframes); - - at.setStereoVolume(1, 1); - - at.play(); - /*buffer needs to be completely full before it'll start playing*/ - while(sz > 0) - { - at.write(audbuf, 0, notifframes*framesz); - sz -= notifframes; - } - } - public void resume() - { - /*poke audio into submission*/ - if (at != null) - at.play(); - } - - public FTEView(Context context) - { - super(context); - - rndr = new FTERenderer(); - setRenderer(rndr); - setFocusable(true); - setFocusableInTouchMode(true); - - audioInit(); - } - - private void sendKey(final boolean presseddown, final int qcode, final int unicode) - { - queueEvent(new Runnable() - { - public void run() - { - FTEDroidEngine.keypress(presseddown?1:0, qcode, unicode); - } - }); - } - private void sendAccelerometer(final float x, final float y, final float z) - { - queueEvent(new Runnable() - { - public void run() - { - FTEDroidEngine.accelerometer(x, y, z); - } - }); - } - @Override - public boolean onTouchEvent(MotionEvent event) - { - final int act = event.getAction(); - final float x = event.getX(); - final float y = event.getY(); - //float p = event.getPressure(); - - queueEvent(new Runnable() - { - public void run() - { - switch(act) - { - case MotionEvent.ACTION_DOWN: - FTEDroidEngine.motion(1, x, y); - break; - case MotionEvent.ACTION_UP: - FTEDroidEngine.motion(2, x, y); - break; - case MotionEvent.ACTION_MOVE: - FTEDroidEngine.motion(0, x, y); - break; - } - } - }); - return true; - } - /* - @Override - public boolean onTrackballEvent(MotionEvent event) - { - int act = event.getAction(); - float x = event.getX(); - float y = event.getY(); - } - */ - private static final int K_UPARROW = 132; - private static final int K_DOWNARROW = 133; - private static final int K_LEFTARROW = 134; - private static final int K_RIGHTARROW = 135; - private int mapKey(int acode, int unicode) - { - switch(acode) - { - case KeyEvent.KEYCODE_DPAD_UP: - return K_UPARROW; - case KeyEvent.KEYCODE_DPAD_DOWN: - return K_DOWNARROW; - case KeyEvent.KEYCODE_DPAD_LEFT: - return K_LEFTARROW; - case KeyEvent.KEYCODE_DPAD_RIGHT: - return K_RIGHTARROW; - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_ENTER: - return '\r'; - case KeyEvent.KEYCODE_BACK: - return 27; - case KeyEvent.KEYCODE_DEL: - return 127; - default: - if (unicode < 128) - return Character.toLowerCase(unicode); - } - return 0; - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - int uc = event.getUnicodeChar(); - sendKey(true, mapKey(keyCode, uc), uc); - return true; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) - { - int uc = event.getUnicodeChar(); - sendKey(false, mapKey(keyCode, uc), uc); - return true; - } - - public void onAccuracyChanged(Sensor sensor, int accuracy) - { - } - - private float gx,gy,gz; - public void onSensorChanged(final SensorEvent event) - { - // alpha is calculated as t / (t + dT) - // with t, the low-pass filter's time-constant - // and dT, the event delivery rate - - final float alpha = 0.8f; - - gx = alpha * gx + (1 - alpha) * event.values[0]; - gy = alpha * gy + (1 - alpha) * event.values[1]; - gz = alpha * gz + (1 - alpha) * event.values[2]; - - sendAccelerometer(event.values[0] - gx, event.values[1] - gy, event.values[2] - gz); - - } - } - - @Override - public void onCreate(Bundle savedInstanceState) - { - //go full-screen - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - requestWindowFeature(Window.FEATURE_NO_TITLE); - - super.onCreate(savedInstanceState); - - view = new FTEView(this); - setContentView(view); - // setContentView(R.layout.main); - - - sensorman = (SensorManager)getSystemService(SENSOR_SERVICE); - sensoracc = sensorman.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - } - - @Override - protected void onResume() - { - super.onResume(); - sensorman.registerListener((SensorEventListener)view, sensoracc, SensorManager.SENSOR_DELAY_GAME); - - view.resume(); - } - - @Override - protected void onStop() - { - sensorman.unregisterListener(view); - super.onStop(); - } - - @Override - protected void onPause() - { - sensorman.unregisterListener(view); - super.onPause(); - } -} +package com.fteqw; + +import javax.microedition.khronos.egl.EGLConfig; +//import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.opengles.GL10; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.Window; +import android.view.WindowManager; + +import android.opengl.GLSurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +import android.hardware.SensorManager; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; + +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; + +public class FTEDroidActivity extends Activity +{ + private SensorManager sensorman; + private Sensor sensoracc; + private FTEView view; + + private class FTERenderer implements GLSurfaceView.Renderer + { + private boolean inited; + @Override + public void onDrawFrame(GL10 gl) + { + if (inited == true) + { + FTEDroidEngine.frame(); + } + } + @Override + public void onSurfaceChanged(GL10 gl, int width, int height) + { + FTEDroidEngine.init(width, height); + inited = true; + } + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) + { + } + } +/* + private class FTEEGLConfig implements GLSurfaceView.EGLConfigChooser + { + @Override + public EGLConfig chooseConfig (javax.microedition.khronos.egl.EGL10 egl, javax.microedition.khronos.egl.EGLDisplay display) + { + int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + EGLConfig[] cfg = new EGLConfig[1]; + int[] num_configs = {0}; + int[] attribs = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT, + egl.EGL_BLUE_SIZE, 5, + egl.EGL_GREEN_SIZE, 6, + egl.EGL_RED_SIZE, 5, + egl.EGL_DEPTH_SIZE, 16, + egl.EGL_STENCIL_SIZE, 8, + egl.EGL_NONE, egl.EGL_NONE + }; + + egl.eglChooseConfig(display, attribs, cfg, 1, num_configs); + return cfg[0]; + } + } +*/ + private class FTEView extends GLSurfaceView implements SensorEventListener + { + private final FTERenderer rndr; + + private byte[] audbuf; + private AudioTrack at; + + private void audioInit() + { + final int notifframes = 2048; + if (at != null) + at.stop(); + int sspeed = 11025; + int speakers = 1; + int sz = 4*AudioTrack.getMinBufferSize(sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT); + if (sz < notifframes*2) + sz = notifframes*2; + + at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT, sz, AudioTrack.MODE_STREAM); + final int framesz = 2; /*mono 16bit*/ + audbuf = new byte[notifframes*framesz]; + + at.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() + { + @Override + public void onMarkerReached(AudioTrack track) + { + } + @Override + public void onPeriodicNotification(AudioTrack track) + { + int avail = FTEDroidEngine.paintaudio(audbuf, audbuf.length); + at.write(audbuf, 0, notifframes*framesz); + } + }); + at.setPositionNotificationPeriod(notifframes); + + at.setStereoVolume(1, 1); + + at.play(); + /*buffer needs to be completely full before it'll start playing*/ + while(sz > 0) + { + at.write(audbuf, 0, notifframes*framesz); + sz -= notifframes; + } + } + public void resume() + { + /*poke audio into submission*/ + if (at != null) + at.play(); + } + + public FTEView(Context context) + { + super(context); + + rndr = new FTERenderer(); +// setEGLConfigChooser(new FTEEGLConfig()); + setRenderer(rndr); + setFocusable(true); + setFocusableInTouchMode(true); + + audioInit(); + } + + private void sendKey(final boolean presseddown, final int qcode, final int unicode) + { + queueEvent(new Runnable() + { + public void run() + { + FTEDroidEngine.keypress(presseddown?1:0, qcode, unicode); + } + }); + } + private void sendAccelerometer(final float x, final float y, final float z) + { + queueEvent(new Runnable() + { + public void run() + { + FTEDroidEngine.accelerometer(x, y, z); + } + }); + } + @Override + public boolean onTouchEvent(MotionEvent event) + { + final int act = event.getAction(); + final float x = event.getX(); + final float y = event.getY(); + //float p = event.getPressure(); + + queueEvent(new Runnable() + { + public void run() + { + switch(act) + { + case MotionEvent.ACTION_DOWN: + FTEDroidEngine.motion(1, x, y); + break; + case MotionEvent.ACTION_UP: + FTEDroidEngine.motion(2, x, y); + break; + case MotionEvent.ACTION_MOVE: + FTEDroidEngine.motion(0, x, y); + break; + } + } + }); + return true; + } + /* + @Override + public boolean onTrackballEvent(MotionEvent event) + { + int act = event.getAction(); + float x = event.getX(); + float y = event.getY(); + } + */ + private static final int K_UPARROW = 132; + private static final int K_DOWNARROW = 133; + private static final int K_LEFTARROW = 134; + private static final int K_RIGHTARROW = 135; + private int mapKey(int acode, int unicode) + { + switch(acode) + { + case KeyEvent.KEYCODE_DPAD_UP: + return K_UPARROW; + case KeyEvent.KEYCODE_DPAD_DOWN: + return K_DOWNARROW; + case KeyEvent.KEYCODE_DPAD_LEFT: + return K_LEFTARROW; + case KeyEvent.KEYCODE_DPAD_RIGHT: + return K_RIGHTARROW; + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + return '\r'; + case KeyEvent.KEYCODE_BACK: + return 27; + case KeyEvent.KEYCODE_DEL: + return 127; + default: + if (unicode < 128) + return Character.toLowerCase(unicode); + } + return 0; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + int uc = event.getUnicodeChar(); + sendKey(true, mapKey(keyCode, uc), uc); + return true; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) + { + int uc = event.getUnicodeChar(); + sendKey(false, mapKey(keyCode, uc), uc); + return true; + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) + { + } + + private float gx,gy,gz; + public void onSensorChanged(final SensorEvent event) + { + // alpha is calculated as t / (t + dT) + // with t, the low-pass filter's time-constant + // and dT, the event delivery rate + + final float alpha = 0.8f; + + gx = alpha * gx + (1 - alpha) * event.values[0]; + gy = alpha * gy + (1 - alpha) * event.values[1]; + gz = alpha * gz + (1 - alpha) * event.values[2]; + + sendAccelerometer(event.values[0] - gx, event.values[1] - gy, event.values[2] - gz); + + } + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + //go full-screen + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + requestWindowFeature(Window.FEATURE_NO_TITLE); + + super.onCreate(savedInstanceState); + + view = new FTEView(this); + setContentView(view); + // setContentView(R.layout.main); + + + sensorman = (SensorManager)getSystemService(SENSOR_SERVICE); + sensoracc = sensorman.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + } + + @Override + protected void onResume() + { + super.onResume(); + sensorman.registerListener((SensorEventListener)view, sensoracc, SensorManager.SENSOR_DELAY_GAME); + + view.resume(); + } + + @Override + protected void onStop() + { + sensorman.unregisterListener(view); + super.onStop(); + } + + @Override + protected void onPause() + { + sensorman.unregisterListener(view); + super.onPause(); + } +} diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 9c408df9a..f62faf8cb 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -36,7 +36,7 @@ typedef struct -extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models; +extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models, ruleset_allow_fbmodels; extern cvar_t r_noaliasshadows; @@ -740,6 +740,13 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) e->light_known = 2; return e->light_known-1; } + if (r_fb_models.ival == 1 && ruleset_allow_fbmodels.ival && (clmodel->engineflags & MDLF_EZQUAKEFBCHEAT) && cls.protocol == CP_QUAKEWORLD && cl.deathmatch) + { + e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1; + e->light_range[0] = e->light_range[1] = e->light_range[2] = 0; + e->light_known = 2; + return e->light_known-1; + } if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index b8b926194..c53ea70ef 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -566,6 +566,18 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) else if (!strcmp(mod->name, "progs/eyes.mdl")) mod->engineflags |= MDLF_NOTREPLACEMENTS|MDLF_DOCRC; + /*handle ezquake-originated cheats that would feck over fte users if fte didn't support + these are the conditions required for r_fb_models on non-players*/ + mod->engineflags |= MDLF_EZQUAKEFBCHEAT; + if ((mod->engineflags & MDLF_DOCRC) || + !strcmp(mod->name, "progs/backpack.mdl") || + !strcmp(mod->name, "progs/gib1.mdl") || + !strcmp(mod->name, "progs/gib2.mdl") || + !strcmp(mod->name, "progs/gib3.mdl") || + !strcmp(mod->name, "progs/h_player.mdl") || + !strncmp(mod->name, "progs/v_", 8)) + mod->engineflags &= ~MDLF_EZQUAKEFBCHEAT; + // call the apropriate loader mod->needload = false; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 9713e73f5..1af0aa264 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -954,6 +954,7 @@ typedef struct model_s #define MDLF_NEEDOVERBRIGHT 0x040 // only overbright these models with gl_overbright_all set #define MDLF_BOLT 0x080 // doesn't produce shadows #define MDLF_NOTREPLACEMENTS 0x100 // can be considered a cheat, disable texture replacements +#define MDLF_EZQUAKEFBCHEAT 0x200 // this is a blatent cheat, one that can disadvantage us fairly significantly if we don't support it. //============================================================================ /* diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index ab31721da..322133b6d 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -260,8 +260,8 @@ enum qcop_e { //------------------------------------- //string manipulation. - OP_ADD_SF, //(char*)c = (char*)a + (float)b - OP_SUB_S, //(float)c = (char*)a - (char*)b + OP_ADD_SF, //(char*)c = (char*)a + (float)b add_fi->i + OP_SUB_S, //(float)c = (char*)a - (char*)b sub_ii->f OP_STOREP_C,//(float)c = *(char*)b = (float)a OP_LOADP_C, //(float)c = *(char*) //------------------------------------- diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index a36ad7eb0..468aea459 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1649,6 +1649,8 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) ddef16_t *d16; ddef32_t *d32; func_t CheckSpawn=0; + void *oldglobals = NULL; + int oldglobalssize = 0; extern edictrun_t tempedict; @@ -1797,6 +1799,14 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) current_progstate->builtins = externs->builtinsfor(num, header_crc); current_progstate->numbuiltins = numbuiltins; } + + if (num == 0 && oldglobals) + { + if (pr_progstate[0].globals_size == oldglobalssize) + memcpy(pr_progstate[0].globals, oldglobals, pr_progstate[0].globals_size); + free(oldglobals); + oldglobals = NULL; + } } else if (!strcmp(qcc_token, "globals")) { @@ -1906,6 +1916,21 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) Sys_Error("Bad key \"%s\" in general block", qcc_token); } + if (oldglobals) + free(oldglobals); + oldglobals = NULL; + if (pr_progstate[0].globals_size) + { + oldglobals = malloc(pr_progstate[0].globals_size); + if (oldglobals) + { + oldglobalssize = pr_progstate[0].globals_size; + memcpy(oldglobals, pr_progstate[0].globals, oldglobalssize); + } + else + printf("Unable to alloc %i bytes\n", pr_progstate[0].globals_size); + } + PRAddressableFlush(progfuncs, -1); resethunk=true; @@ -2107,6 +2132,10 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) sv_num_edicts = numents; } + if (oldglobals) + free(oldglobals); + oldglobals = NULL; + if (resethunk) { return entsize; @@ -2448,6 +2477,7 @@ retry: current_progstate->statements = (void *)((qbyte *)pr_progs + pr_progs->ofs_statements); glob = pr_globals = (void *)((qbyte *)pr_progs + pr_progs->ofs_globals); + current_progstate->globals_size = pr_progs->numglobals*sizeof(*pr_globals); pr_linenums=NULL; pr_types=NULL; diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 9dc58c51d..795dcb5e0 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -186,6 +186,7 @@ typedef struct progstate_s void *statements; // void *global_struct; float *globals; // same as pr_global_struct + int globals_size; // in bytes typeinfo_t *types; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index cd55e5643..583aa0277 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -4300,12 +4300,21 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) tmp = QCC_PR_Expression (TOP_PRIORITY, 0); QCC_PR_Expect("]"); + /*if its a pointer that got dereferenced, follow the type*/ if (!idx && t->type == ev_pointer && !d->arraysize) t = t->aux_type; if (!idx && d->type->type == ev_pointer) { - /*no bounds checks*/ + /*no bounds checks on pointer dereferences*/ + } + else if (!idx && d->type->type == ev_string) + { + /*automatic runtime bounds checks on strings, I'm not going to check this too much...*/ + } + else if (!((!idx)?d->arraysize:t->arraysize)) + { + QCC_PR_ParseErrorPrintDef(0, d, "array index on non-array"); } else if (tmp->constant) { @@ -4332,6 +4341,8 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) else tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL); } + + /*calc the new index*/ if (idx) idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL); else @@ -4403,6 +4414,10 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) } d->type = t; } + else if (d->type->type == ev_string) + { + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(idx, ev_float, true), NULL); + } else if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) { /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/ diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 6017cbd50..a3b9d46b0 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -1558,6 +1558,7 @@ void QCC_PR_LexVector (void) default: QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant"); } + pr_file_p++; if (*pr_file_p != '\'') QCC_PR_ParseError (ERR_INVALIDVECTORIMMEDIATE, "Bad character constant"); pr_file_p++; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index abd49242c..90dfaec48 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -319,11 +319,13 @@ int QCC_CopyString (char *str) int old; char *s; + if (!str) + return 0; + if (!*str) + return 1; + if (opt_noduplicatestrings) { - if (!str || !*str) - return 0; - for (s = strings; s < strings+strofs; s++) if (!strcmp(s, str)) { @@ -488,7 +490,7 @@ void QCC_InitData (void) qcc_sourcefile = NULL; numstatements = 1; - strofs = 1; + strofs = 2; numfunctions = 1; numglobaldefs = 1; numfielddefs = 1; @@ -784,7 +786,7 @@ pbool QCC_WriteData (int crc) dd->s_name = QCC_CopyString (def->name); dd->ofs = G_INT(def->ofs); } - else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings)) + else if ((def->scope||def->constant) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings))) { if (opt_constant_names) { @@ -2992,7 +2994,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine QCC_PurgeTemps(); strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS); - strofs = 1; + strofs = 2; statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS); numstatements = 0; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index eb1ba8769..8e4d6d127 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -8689,7 +8689,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"precache_file", PF_precache_file, 68, 68, 68, 0, "void(string s)"}, //68 {"makestatic", PF_makestatic, 69, 69, 69, 0, "void(entity e)"}, //69 - {"changelevel", PF_changelevel, 70, 70, 70, 0, "void(string mapname)"}, //70 + {"changelevel", PF_changelevel, 70, 70, 70, 0, "void(string mapname, optional string newmapstartspot)"}, //70 {"lightstylevalue", PF_lightstylevalue, 0, 0, 71, 0, "float(float lstyle)"}, //70 {"cvar_set", PF_cvar_set, 72, 72, 72, 0, "void(string cvarname, string valuetoset)"}, //72 @@ -9239,8 +9239,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"cvar_description",PF_cvar_description,0, 0, 0, 518, "string(string cvarname)"}, {"gettime", PF_Fixme, 0, 0, 0, 519, "float(optional float timetype)"}, -// {"loadfromdata", VM_loadfromdata, 0, 0, 0, 529, "??" STUB}, -// {"loadfromfile", VM_loadfromfile, 0, 0, 0, 530, "??" STUB}, + {"loadfromdata", PF_loadfromdata, 0, 0, 0, 529, "void(string s)"}, + {"loadfromfile", PF_loadfromfile, 0, 0, 0, 530, "void(string s)"}, // {"setpause", VM_SV_setpause, 0, 0, 0, 531, "void(float pause)" STUB}, //end dp extras @@ -9255,10 +9255,11 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"physics_addforce",PF_Ignore, 0, 0, 0, 541, "void(entity e, vector force, vector relative_ofs)" STUB}, {"physics_addtorque",PF_Ignore, 0, 0, 0, 542, "void(entity e, vector torque)" STUB}, -//VM_callfunction, // #605 -//VM_writetofile, // #606 -//VM_isfunction, // #607 -//VM_parseentitydata, // #613 + {"callfunction", PF_callfunction, 0, 0, 0, 605, "void(.../*, string funcname*/)"}, + {"writetofile", PF_writetofile, 0, 0, 0, 606, "void(float fh, entity e)"}, + {"isfunction", PF_isfunction, 0, 0, 0, 607, "float(string s)"}, + {"parseentitydata", PF_parseentitydata, 0, 0, 0, 608, "void(entity e, string s)"}, + //VM_SV_getextresponse, // #624 string getextresponse(void) {"sprintf", PF_sprintf, 0, 0, 0, 627, "string(...)" STUB}, @@ -9957,6 +9958,7 @@ void PR_DumpPlatform_f(void) {"FILE_READ", "const float", QW|NQ|CS, FRIK_FILE_READ}, {"FILE_APPEND", "const float", QW|NQ|CS, FRIK_FILE_APPEND}, {"FILE_WRITE", "const float", QW|NQ|CS, FRIK_FILE_WRITE}, + {"FILE_READNL", "const float", QW|NQ|CS, FRIK_FILE_READNL}, {"FILE_MMAP_READ", "const float", QW|NQ|CS, FRIK_FILE_MMAP_READ}, {"FILE_MMAP_RW", "const float", QW|NQ|CS, FRIK_FILE_MMAP_RW}, diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 609eaf597..f17fbcbd8 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -655,11 +655,14 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea // load the edicts out of the savegame file // the rest of the file is sent directly to the progs engine. - Q_SetProgsParms(false); - - PR_Configure(svprogfuncs, -1, MAX_PROGS); - PR_RegisterFields(); - PR_InitEnts(svprogfuncs, sv.world.max_edicts); + /*hexen2's gamecode doesn't have SAVE set on all variables, in which case we must clobber them, and run the risk that they were set at map load time, but clear in the savegame.*/ + if (progstype != PROG_H2) + { + Q_SetProgsParms(false); + PR_Configure(svprogfuncs, -1, MAX_PROGS); + PR_RegisterFields(); + PR_InitEnts(svprogfuncs, sv.world.max_edicts); + } modelpos = VFS_TELL(f); LoadModelsAndSounds(f); @@ -854,26 +857,29 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame) VFS_PRINTF (f, "%i\n", CACHEGAME_VERSION); SV_SavegameComment (comment); VFS_PRINTF (f, "%s\n", comment); - for (cl = svs.clients, clnum=0; clnum < MAX_CLIENTS; cl++,clnum++)//fake dropping + if (!dontharmgame) { - if ((cl->state < cs_spawned && !cl->istobeloaded) || dontharmgame) //don't drop if they are still connecting + for (cl = svs.clients, clnum=0; clnum < MAX_CLIENTS; cl++,clnum++)//fake dropping { - continue; - } - else if (!cl->spectator) - { - // call the prog function for removing a client - // this will set the body to a dead frame, among other things - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect); - sv.spawned_client_slots--; - } - else if (SpectatorDisconnect) - { - // call the prog function for removing a client - // this will set the body to a dead frame, among other things - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + if (cl->state < cs_spawned && !cl->istobeloaded) //don't drop if they are still connecting + { + cl->edict->v->solid = 0; + } + else if (!cl->spectator) + { + // call the prog function for removing a client + // this will set the body to a dead frame, among other things + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); + PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect); + sv.spawned_client_slots--; + } + else if (SpectatorDisconnect) + { + // call the prog function for removing a client + // this will set the body to a dead frame, among other things + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); + PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + } } } VFS_PRINTF (f, "%d\n", progstype); @@ -1053,13 +1059,14 @@ void SV_Savegame_f (void) void SV_Loadgame_f (void) { levelcache_t *cache; - char str[MAX_LOCALINFO_STRING+1], *trim; - char savename[MAX_QPATH]; + unsigned char str[MAX_LOCALINFO_STRING+1], *trim; + unsigned char savename[MAX_QPATH]; vfsfile_t *f; - char filename[MAX_OSPATH]; + unsigned char filename[MAX_OSPATH]; int version; int clnum; int slots; + int loadzombies = 0; client_t *cl; gametype_e gametype; @@ -1130,6 +1137,7 @@ void SV_Loadgame_f (void) cl->state = cs_zombie; cl->connection_started = realtime+20; cl->istobeloaded = true; + loadzombies++; memset(&cl->netchan, 0, sizeof(cl->netchan)); for (len = 0; len < NUM_SPAWN_PARMS; len++) @@ -1237,6 +1245,7 @@ void SV_Loadgame_f (void) SV_LoadLevelCache(savename, str, "", true); sv.allocated_client_slots = slots; + sv.spawned_client_slots += loadzombies; } #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 0b91f31d3..bd9b25e9c 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2296,6 +2296,9 @@ client_t *SVC_DirectConnect(void) newcl->realip_ping = (((rand()^(rand()<<8) ^ *(int*)&realtime)&0xffffff)<<8) | (newcl-svs.clients); + if (newcl->istobeloaded) + newcl->playerclass = newcl->edict->xv->playerclass; + // parse some info from the info strings SV_ExtractFromUserinfo (newcl); SV_GenerateBasicUserInfo (newcl); @@ -3462,7 +3465,7 @@ void SV_CheckTimeouts (void) if (cl->netchan.last_received < droptime && cl->netchan.remote_address.type != NA_LOOPBACK && cl->protocol != SCP_BAD) { SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTTIMEDOUT, cl->name); SV_DropClient (cl); - cl->state = cs_free; // don't bother with zombie state + cl->state = cs_free; // don't bother with zombie state for local player. } } if (cl->state == cs_zombie && @@ -3479,9 +3482,11 @@ void SV_CheckTimeouts (void) PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect); sv.spawned_client_slots--; - host_client->istobeloaded=false; + cl->istobeloaded=false; SV_BroadcastTPrintf (PRINT_HIGH, STL_LOADZOMIBETIMEDOUT, cl->name); +// cl->state = cs_zombie; // the real zombieness starts now +// cl->connection_started = realtime; } } } @@ -4548,6 +4553,7 @@ void SV_ExtractFromUserinfo (client_t *cl) client_t *client; int dupc = 1; char newname[80], basic[80]; + extern cvar_t rank_filename; val = Info_ValueForKey (cl->userinfo, "team"); Q_strncpyz (cl->team, val, sizeof(cl->teambuf)); @@ -4622,7 +4628,7 @@ void SV_ExtractFromUserinfo (client_t *cl) if (*cl->name && cl->state >= cs_spawned && !cl->spectator) { - SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTNAMECHANGE, cl->name, val); + SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTNAMECHANGE, cl->name, newname); } Q_strncpyz (cl->name, newname, sizeof(cl->namebuf)); @@ -4633,7 +4639,7 @@ void SV_ExtractFromUserinfo (client_t *cl) #endif #ifdef SVRANKING } - else if (cl->state >= cs_spawned) + else if (cl->state >= cs_spawned && *rank_filename.string) SV_ClientPrintf(cl, PRINT_HIGH, "Your rankings name has not been changed\n"); #endif } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index fa0ff0e3f..5746d7e87 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1934,12 +1934,18 @@ void SV_UpdateToReliableMessages (void) { if (strcmp(host_client->name, name)) { + char oname[80]; + Q_strncpyz(oname, host_client->name, sizeof(oname)); + +#pragma warningmsg("Debug line to try to find OneManClan's issue\n"); + Con_Printf("DEBUG: .netname= \"%s\" -> \"%s\" (f=%x n=%p b=%p)\n", oname, name, host_client->edict->v->netname, host_client->name, host_client->namebuf); + Con_DPrintf("Client %s programatically renamed to %s\n", host_client->name, name); Info_SetValueForKey(host_client->userinfo, "name", name, sizeof(host_client->userinfo)); - if (!strcmp(Info_ValueForKey(host_client->userinfo, "name"), name)) - { - SV_ExtractFromUserinfo (host_client); + SV_ExtractFromUserinfo (host_client); + if (strcmp(oname, host_client->name)) + { MSG_WriteByte (&sv.reliable_datagram, svc_setinfo); MSG_WriteByte (&sv.reliable_datagram, i); MSG_WriteString (&sv.reliable_datagram, "name"); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index b94d7fa9c..c7c80b841 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1513,6 +1513,7 @@ void SV_Spawn_f (void) { split->entgravity = ent->xv->gravity; split->maxspeed = ent->xv->maxspeed; + split->playerclass = ent->xv->playerclass; } else {