fix playdemo not working straight after record.
make a guess at the currently applied preset. fix issues with vid_reload on preset changes being buggy. fix erroneous weapon flashes due to limited precision. try to fix rogue finale. fix issue with vid_restart crashing with directinput active. work around emscripten rand entropy, at least as far as particles are concerned. properly implement te_explosion2 (for rogue mission pack). drastically reduce submodel polyoffsets in the webgl port, because firefox's depth precision is 16 bit or something stupid. fix rogue ibar background not being used with qw hud. added terrain editor feature to edit the bsp's entity lump. this also works with .bsps. added console command to reload the map/apply those ent changes but leaving the players how they were (lets hope enemy etc stuff doesn't bug out...) force-enabled airstep when travelling fast. this is to partly replicate nq player physics in order to fix windtunnels on r1m5 iirc. added some more effects to the 'high' particle effect, in order to make rogue feel a little more loved. fix for rogue buzzsaws. rework webgl pointer locks. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4965 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
c7b1e544ee
commit
e99354bd20
42 changed files with 1388 additions and 372 deletions
|
@ -922,6 +922,8 @@ void CL_Stop_f (void)
|
|||
cls.demooutfile = NULL;
|
||||
cls.demorecording = false;
|
||||
Con_Printf ("Completed demo\n");
|
||||
|
||||
FS_FlushFSHash();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4829,6 +4829,8 @@ void CL_LinkViewModel(void)
|
|||
&& r_drawviewmodelinvis.value < 1)
|
||||
alpha *= r_drawviewmodelinvis.value;
|
||||
|
||||
//FIXME: scale alpha by the player's alpha too
|
||||
|
||||
if (alpha <= 0)
|
||||
return;
|
||||
|
||||
|
@ -4910,6 +4912,7 @@ void CL_LinkViewModel(void)
|
|||
*/
|
||||
CLQ1_AddPowerupShell(V_AddEntity(&ent), true, plstate?plstate->effects:0);
|
||||
|
||||
//small hack to mask depth so only the front faces of the weaponmodel appear (no glitchy intra faces).
|
||||
if (alpha < 1 && qrenderer == QR_OPENGL)
|
||||
{
|
||||
ent.forcedshader = R_RegisterShader("viewmodeldepthmask", SUF_NONE,
|
||||
|
|
|
@ -5219,6 +5219,7 @@ void CL_ExecInitialConfigs(char *resetcommand)
|
|||
Cbuf_Execute (); //make sure any pending console commands are done with. mostly, anyway...
|
||||
SCR_ShowPic_Clear(true);
|
||||
|
||||
Cbuf_AddText("alias restart_ents \"changelevel . .\"\n",RESTRICT_LOCAL);
|
||||
Cbuf_AddText("alias restart \"changelevel .\"\n",RESTRICT_LOCAL);
|
||||
Cbuf_AddText("alias startmap_sp \"map start\"\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("unbindall\n", RESTRICT_LOCAL);
|
||||
|
|
|
@ -24,7 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
void CL_GetNumberedEntityInfo (int num, float *org, float *ang);
|
||||
void CLDP_ParseDarkPlaces5Entities(void);
|
||||
void CL_SetStatInt (int pnum, int stat, int value);
|
||||
static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue);
|
||||
static void CL_SetStatInt (int pnum, int stat, int ivalue);
|
||||
static qboolean CL_CheckModelResources (char *name);
|
||||
|
||||
char cl_dp_csqc_progsname[128];
|
||||
|
@ -2898,13 +2899,14 @@ void CLQW_ParseServerData (void)
|
|||
#ifndef CLIENTONLY
|
||||
Info_SetValueForStarKey (svs.info, "*gamedir", str, MAX_SERVERINFO_STRING);
|
||||
#endif
|
||||
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
|
||||
}
|
||||
|
||||
CL_ClearState ();
|
||||
Stats_NewMap();
|
||||
cl.servercount = svcnt;
|
||||
|
||||
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
|
||||
|
||||
cl.teamfortress = !Q_strcasecmp(str, "fortress");
|
||||
|
||||
if (cl.gamedirchanged)
|
||||
|
@ -3569,10 +3571,10 @@ void CLNQ_ParseClientdata (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
int weaponmodel = 0, armor = 0, weaponframe = 0, health = 0, currentammo = 0, shells = 0, nails = 0, rockets = 0, cells = 0, activeweapon = 0;
|
||||
int weaponmodel = 0, armour = 0, weaponframe = 0, health = 0, currentammo = 0, shells = 0, nails = 0, rockets = 0, cells = 0, activeweapon = 0;
|
||||
|
||||
if (bits & SU_WEAPONFRAME) weaponframe |= (unsigned char)MSG_ReadByte();
|
||||
if (bits & SU_ARMOR) armor |= (unsigned char)MSG_ReadByte();
|
||||
if (bits & SU_ARMOR) armour |= (unsigned char)MSG_ReadByte();
|
||||
if (bits & SU_WEAPONMODEL) weaponmodel |= (unsigned char)MSG_ReadByte();
|
||||
health |= MSG_ReadShort();
|
||||
currentammo |= MSG_ReadByte();
|
||||
|
@ -3587,7 +3589,7 @@ void CLNQ_ParseClientdata (void)
|
|||
if (bits & FITZSU_WEAPONMODEL2)
|
||||
weaponmodel |= MSG_ReadByte() << 8;
|
||||
if (bits & FITZSU_ARMOR2)
|
||||
armor |= MSG_ReadByte() << 8;
|
||||
armour |= MSG_ReadByte() << 8;
|
||||
if (bits & FITZSU_AMMO2)
|
||||
currentammo |= MSG_ReadByte() << 8;
|
||||
if (bits & FITZSU_SHELLS2)
|
||||
|
@ -3605,7 +3607,7 @@ void CLNQ_ParseClientdata (void)
|
|||
}
|
||||
|
||||
CL_SetStatInt(0, STAT_WEAPONFRAME, weaponframe);
|
||||
CL_SetStatInt(0, STAT_ARMOR, armor);
|
||||
CL_SetStatInt(0, STAT_ARMOR, armour);
|
||||
CL_SetStatInt(0, STAT_WEAPONMODELI, weaponmodel);
|
||||
|
||||
CL_SetStatInt(0, STAT_HEALTH, health);
|
||||
|
@ -4814,7 +4816,8 @@ void CL_SetStatMovevar(int pnum, int stat, float value)
|
|||
}
|
||||
}
|
||||
|
||||
void CL_SetStatInt (int pnum, int stat, int value)
|
||||
//the two values are expected to be the same, they're just both provided for precision.
|
||||
static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
|
||||
{
|
||||
if (stat < 0 || stat >= MAX_CL_STATS)
|
||||
return;
|
||||
|
@ -4825,57 +4828,39 @@ void CL_SetStatInt (int pnum, int stat, int value)
|
|||
cl.oldgametime = cl.gametime;
|
||||
cl.oldgametimemark = cl.gametimemark;
|
||||
|
||||
cl.gametime = value * 0.001;
|
||||
cl.gametime = fvalue * 0.001;
|
||||
cl.gametimemark = realtime;
|
||||
}
|
||||
|
||||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
{
|
||||
extern int cls_lastto;
|
||||
cl.players[cls_lastto].stats[stat]=value;
|
||||
cl.players[cls_lastto].statsf[stat]=value;
|
||||
cl.players[cls_lastto].stats[stat]=ivalue;
|
||||
cl.players[cls_lastto].statsf[stat]=fvalue;
|
||||
|
||||
for (pnum = 0; pnum < cl.splitclients; pnum++)
|
||||
if (cl.playerview[pnum].cam_spec_track == cls_lastto && cl.playerview[pnum].cam_state != CAM_FREECAM)
|
||||
CL_SetStat_Internal(pnum, stat, value, value);
|
||||
CL_SetStat_Internal(pnum, stat, ivalue, fvalue);
|
||||
}
|
||||
else
|
||||
CL_SetStat_Internal(pnum, stat, value, value);
|
||||
|
||||
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
|
||||
CL_SetStatMovevar(pnum, stat, *(float*)&value); //DP sucks.
|
||||
}
|
||||
void CL_SetStatFloat (int pnum, int stat, float value)
|
||||
{
|
||||
if (stat < 0 || stat >= MAX_CL_STATS)
|
||||
return;
|
||||
// Host_EndGame ("CL_SetStat: %i is invalid", stat);
|
||||
|
||||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
{
|
||||
extern int cls_lastto;
|
||||
cl.players[cls_lastto].statsf[stat]=value;
|
||||
cl.players[cls_lastto].stats[stat]=value;
|
||||
|
||||
for (pnum = 0; pnum < cl.splitclients; pnum++)
|
||||
if (cl.playerview[pnum].cam_spec_track == cls_lastto && cl.playerview[pnum].cam_state != CAM_FREECAM)
|
||||
{
|
||||
cl.playerview[pnum].statsf[stat] = value;
|
||||
cl.playerview[pnum].stats[stat] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.playerview[pnum].statsf[stat] = value;
|
||||
cl.playerview[pnum].stats[stat] = value;
|
||||
}
|
||||
CL_SetStat_Internal(pnum, stat, ivalue, fvalue);
|
||||
|
||||
if (stat == STAT_VIEWHEIGHT && ((cls.z_ext & Z_EXT_VIEWHEIGHT) || cls.protocol == CP_NETQUAKE))
|
||||
cl.playerview[pnum].viewheight = value;
|
||||
cl.playerview[pnum].viewheight = fvalue;
|
||||
|
||||
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
||||
{
|
||||
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
|
||||
CL_SetStatMovevar(pnum, stat, value);
|
||||
CL_SetStatMovevar(pnum, stat, fvalue);
|
||||
else
|
||||
CL_SetStatMovevar(pnum, stat, *(float*)&ivalue); //DP sucks.
|
||||
}
|
||||
}
|
||||
static void CL_SetStatInt (int pnum, int stat, int ivalue)
|
||||
{
|
||||
CL_SetStatNumeric(pnum,stat,ivalue,ivalue);
|
||||
}
|
||||
|
||||
void CL_SetStatString (int pnum, int stat, char *value)
|
||||
{
|
||||
if (stat < 0 || stat >= MAX_CL_STATS)
|
||||
|
@ -6039,6 +6024,14 @@ void CLQW_ParseServerMessage (void)
|
|||
inf->packet_entities.fixangles[0] = 2;
|
||||
VectorCopy(demoangles, inf->packet_entities.fixedangles[0]);
|
||||
}
|
||||
else if (cl.intermission)
|
||||
{
|
||||
for (destsplit = 0; destsplit < cl.splitclients; destsplit++)
|
||||
{
|
||||
inf->packet_entities.fixangles[destsplit] = 2;
|
||||
VectorCopy(cl.playerview[destsplit].intermissionangles, inf->packet_entities.fixedangles[destsplit]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// if recording demos, copy the message out
|
||||
|
@ -6191,7 +6184,8 @@ void CLQW_ParseServerMessage (void)
|
|||
case svcfte_setangledelta:
|
||||
for (i=0 ; i<3 ; i++)
|
||||
cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 ();
|
||||
// VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
|
||||
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
|
||||
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
|
||||
break;
|
||||
case svc_setangle:
|
||||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
|
@ -6362,14 +6356,12 @@ void CLQW_ParseServerMessage (void)
|
|||
case svcqw_updatestatbyte:
|
||||
i = MSG_ReadByte ();
|
||||
j = MSG_ReadByte ();
|
||||
CL_SetStatFloat (destsplit, i, j);
|
||||
CL_SetStatInt (destsplit, i, j);
|
||||
CL_SetStatNumeric(destsplit, i, j, j);
|
||||
break;
|
||||
case svcqw_updatestatlong:
|
||||
i = MSG_ReadByte ();
|
||||
j = MSG_ReadLong (); //make qbyte if nq compatability?
|
||||
CL_SetStatFloat (destsplit, i, j);
|
||||
CL_SetStatInt (destsplit, i, j);
|
||||
CL_SetStatNumeric (destsplit, i, j, j);
|
||||
break;
|
||||
|
||||
case svcfte_updatestatstring:
|
||||
|
@ -6380,8 +6372,7 @@ void CLQW_ParseServerMessage (void)
|
|||
case svcfte_updatestatfloat:
|
||||
i = MSG_ReadByte();
|
||||
f = MSG_ReadFloat();
|
||||
CL_SetStatInt (destsplit, i, f);
|
||||
CL_SetStatFloat (destsplit, i, f);
|
||||
CL_SetStatNumeric (destsplit, i, f, f);
|
||||
break;
|
||||
|
||||
case svc_spawnstaticsound:
|
||||
|
@ -7201,14 +7192,12 @@ void CLNQ_ParseServerMessage (void)
|
|||
case svcnq_updatestatlong:
|
||||
i = MSG_ReadByte ();
|
||||
j = MSG_ReadLong ();
|
||||
CL_SetStatFloat (0, i, j);
|
||||
CL_SetStatInt (0, i, j);
|
||||
CL_SetStatNumeric (0, i, j, j);
|
||||
break;
|
||||
case svcdp_updatestatbyte:
|
||||
i = MSG_ReadByte ();
|
||||
j = MSG_ReadByte ();
|
||||
CL_SetStatFloat (0, i, j);
|
||||
CL_SetStatInt (0, i, j);
|
||||
CL_SetStatNumeric (0, i, j, j);
|
||||
break;
|
||||
case svcfte_updatestatstring:
|
||||
i = MSG_ReadByte();
|
||||
|
@ -7219,8 +7208,7 @@ void CLNQ_ParseServerMessage (void)
|
|||
i = MSG_ReadByte();
|
||||
{
|
||||
float f = MSG_ReadFloat();
|
||||
CL_SetStatInt (destsplit, i, f);
|
||||
CL_SetStatFloat (destsplit, i, f);
|
||||
CL_SetStatNumeric (destsplit, i, f, f);
|
||||
}
|
||||
break;
|
||||
case svc_setangle:
|
||||
|
|
|
@ -918,12 +918,14 @@ void CL_PredictMovePNum (int seat)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
|
||||
if (0)//cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
|
||||
{
|
||||
//quakeworld locks view position once you hit intermission.
|
||||
VectorCopy (pv->intermissionangles, pv->simangles);
|
||||
return;
|
||||
}
|
||||
else if (cl.intermission)
|
||||
lerpangles = false; //will do angles later.
|
||||
else
|
||||
{
|
||||
if (cl.currentpackentities && cl.currentpackentities->fixangles[seat])
|
||||
|
@ -974,7 +976,7 @@ void CL_PredictMovePNum (int seat)
|
|||
|
||||
//these things also force-disable prediction
|
||||
if ((cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) ||
|
||||
cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || CAM_ISLOCKED(pv))
|
||||
cl.intermission || cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || CAM_ISLOCKED(pv))
|
||||
{
|
||||
nopred = true;
|
||||
}
|
||||
|
@ -1268,7 +1270,12 @@ void CL_PredictMovePNum (int seat)
|
|||
else
|
||||
VectorCopy(pmove.gravitydir, pv->gravitydir);
|
||||
|
||||
if (le && pv->cam_state == CAM_FREECAM)
|
||||
if (cl.intermission && le)
|
||||
{
|
||||
VectorCopy(le->angles, pv->simangles);
|
||||
VectorCopy(pv->simangles, pv->viewangles);
|
||||
}
|
||||
else if (le && pv->cam_state == CAM_FREECAM)
|
||||
{
|
||||
//keep the entity tracking the prediction position, so mirrors don't go all weird
|
||||
VectorMA(pv->simorg, -pv->crouch, pv->gravitydir, le->origin);
|
||||
|
|
|
@ -541,6 +541,8 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
|
|||
{
|
||||
int w, h;
|
||||
R_GetShaderSizes(pic, &w, &h, false);
|
||||
w *= 24.0/h;
|
||||
h = 24;
|
||||
y+= 16;
|
||||
R2D_ScalePic ( (vid.width-w)/2, 16, w, h, pic);
|
||||
y+= h;
|
||||
|
|
|
@ -370,9 +370,9 @@ tentsfx_t tentsfx[] =
|
|||
|
||||
vec3_t playerbeam_end[MAX_SPLITS];
|
||||
|
||||
struct associatedeffect
|
||||
typedef struct associatedeffect_s
|
||||
{
|
||||
struct associatedeffect *next;
|
||||
struct associatedeffect_s *next;
|
||||
char mname[MAX_QPATH];
|
||||
char pname[MAX_QPATH];
|
||||
enum
|
||||
|
@ -381,13 +381,14 @@ struct associatedeffect
|
|||
AE_EMIT,
|
||||
AE_REPLACE
|
||||
} type;
|
||||
} *associatedeffect;
|
||||
} associatedeffect_t;
|
||||
associatedeffect_t *associatedeffect;
|
||||
void CL_AssociateEffect_f(void)
|
||||
{
|
||||
char *modelname = Cmd_Argv(1);
|
||||
char *effectname = Cmd_Argv(2);
|
||||
int type = atoi(Cmd_Argv(3));
|
||||
struct associatedeffect *ae;
|
||||
struct associatedeffect_s *ae;
|
||||
if (!strcmp(Cmd_Argv(0), "r_trail"))
|
||||
type = AE_TRAIL;
|
||||
else
|
||||
|
@ -473,7 +474,7 @@ void CL_InitTEnts (void)
|
|||
|
||||
void CL_ShutdownTEnts (void)
|
||||
{
|
||||
struct associatedeffect *ae;
|
||||
struct associatedeffect_s *ae;
|
||||
while(associatedeffect)
|
||||
{
|
||||
ae = associatedeffect;
|
||||
|
@ -496,7 +497,7 @@ void CL_ClearTEntParticleState (void)
|
|||
|
||||
void P_LoadedModel(model_t *mod)
|
||||
{
|
||||
struct associatedeffect *ae;
|
||||
struct associatedeffect_s *ae;
|
||||
|
||||
mod->particleeffect = P_INVALID;
|
||||
mod->particletrail = P_INVALID;
|
||||
|
@ -1104,7 +1105,7 @@ void CL_ParseTEnt (void)
|
|||
type = TEQW_BEAM;
|
||||
break;
|
||||
case TE_EXPLOSION:
|
||||
type = TE_EXPLOSIONNOSPRITE;
|
||||
type = TEQW_EXPLOSIONNOSPRITE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1334,7 +1335,7 @@ void CL_ParseTEnt (void)
|
|||
ex->endalpha = ex->startalpha; //don't fade out
|
||||
}
|
||||
break;
|
||||
case TE_EXPLOSIONNOSPRITE: //nq-style, no sprite
|
||||
case TEQW_EXPLOSIONNOSPRITE: //nq-style, no sprite
|
||||
case TE_EXPLOSION: //qw-style, with (optional) sprite
|
||||
// particles
|
||||
pos[0] = MSG_ReadCoord ();
|
||||
|
@ -1379,13 +1380,17 @@ void CL_ParseTEnt (void)
|
|||
{
|
||||
int colorStart;
|
||||
int colorLength;
|
||||
int ef;
|
||||
pos[0] = MSG_ReadCoord ();
|
||||
pos[1] = MSG_ReadCoord ();
|
||||
pos[2] = MSG_ReadCoord ();
|
||||
colorStart = MSG_ReadByte ();
|
||||
colorLength = MSG_ReadByte ();
|
||||
if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
|
||||
P_RunParticleEffect(pos, NULL, (colorStart + colorLength/2), 512);
|
||||
|
||||
ef = P_FindParticleType(va("TE_EXPLOSION2_%i_%i", colorStart, colorLength));
|
||||
if (ef == P_INVALID)
|
||||
ef = pt_explosion;
|
||||
P_RunParticleEffectType(pos, NULL, 1, ef);
|
||||
if (r_explosionlight.value)
|
||||
{
|
||||
dl = CL_AllocDlight (0);
|
||||
|
@ -1591,11 +1596,11 @@ void CL_ParseTEnt (void)
|
|||
break;
|
||||
|
||||
case TEDP_SPARK:
|
||||
pos[0] = MSG_ReadCoord ();
|
||||
pos[0] = MSG_ReadCoord (); //org
|
||||
pos[1] = MSG_ReadCoord ();
|
||||
pos[2] = MSG_ReadCoord ();
|
||||
|
||||
pos2[0] = MSG_ReadChar ();
|
||||
pos2[0] = MSG_ReadChar (); //vel
|
||||
pos2[1] = MSG_ReadChar ();
|
||||
pos2[2] = MSG_ReadChar ();
|
||||
|
||||
|
@ -1606,6 +1611,8 @@ void CL_ParseTEnt (void)
|
|||
break;
|
||||
|
||||
case TEDP_BLOODSHOWER:
|
||||
{
|
||||
vec3_t vel = {0,0,0};
|
||||
pos[0] = MSG_ReadCoord ();
|
||||
pos[1] = MSG_ReadCoord ();
|
||||
pos[2] = MSG_ReadCoord ();
|
||||
|
@ -1614,14 +1621,11 @@ void CL_ParseTEnt (void)
|
|||
pos2[1] = MSG_ReadCoord ();
|
||||
pos2[2] = MSG_ReadCoord ();
|
||||
|
||||
cnt = MSG_ReadCoord (); //speed
|
||||
vel[2] = -MSG_ReadCoord ();
|
||||
|
||||
cnt = MSG_ReadShort ();
|
||||
|
||||
{
|
||||
VectorAdd(pos, pos2, pos);
|
||||
VectorScale(pos, 0.5, pos);
|
||||
P_RunParticleEffectTypeString(pos, NULL, cnt, "te_bloodshower");
|
||||
P_RunParticleCube(P_FindParticleType("te_bloodshower"), pos, pos2, vel, vel, cnt, 0, false, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1684,21 +1688,11 @@ void CL_ParseTEnt (void)
|
|||
pos[1] = MSG_ReadCoord ();
|
||||
pos[2] = MSG_ReadCoord ();
|
||||
|
||||
// light
|
||||
dl = CL_AllocDlight (0);
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 200;
|
||||
dl->decay = 1000;
|
||||
dl->die = cl.time + 0.2;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 1.0;
|
||||
dl->color[2] = 1.0;
|
||||
|
||||
// stain (Hopefully this is close to how DP does it)
|
||||
if (cl_legacystains.ival) Surf_AddStain(pos, -10, -10, -10, 30);
|
||||
|
||||
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_plasmaburn"), 0, NULL, NULL))
|
||||
P_ParticleTrailIndex(pos, pos2, 15, 0, NULL);
|
||||
if (P_RunParticleEffectType(pos, NULL, 1, P_FindParticleType("te_plasmaburn")))
|
||||
P_RunParticleEffect(pos, vec3_origin, 15, 50);
|
||||
break;
|
||||
|
||||
case TEDP_TEI_G3: //nexuiz's nex beam
|
||||
|
|
|
@ -770,6 +770,7 @@ void INS_CloseDInput (void)
|
|||
FreeLibrary(hInstDI);
|
||||
hInstDI = NULL;
|
||||
pDirectInputCreate = NULL;
|
||||
pDirectInputCreateEx = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -832,11 +832,11 @@ static void ApplyPreset (int presetnum)
|
|||
//this function is written backwards, to ensure things work properly in configs etc.
|
||||
|
||||
// TODO: work backwards and only set cvars once
|
||||
Cbuf_InsertText("vid_reload\n", RESTRICT_LOCAL, true);
|
||||
for (i = presetnum; i >= 0; i--)
|
||||
{
|
||||
Cbuf_InsertText(presetexec[i], RESTRICT_LOCAL, true);
|
||||
}
|
||||
Cbuf_InsertText("vid_reload\n", RESTRICT_LOCAL, true);
|
||||
forcesaveprompt = true;
|
||||
}
|
||||
|
||||
|
@ -857,10 +857,26 @@ void M_Menu_Preset_f (void)
|
|||
MB_END()
|
||||
};
|
||||
static menuresel_t resel;
|
||||
int item;
|
||||
extern cvar_t r_drawflat;
|
||||
menu = M_Options_Title(&y, 0);
|
||||
MC_AddBulk(menu, &resel, bulk, 16, 216, y);
|
||||
//bottoms up! highlight 'normal' as the default option
|
||||
menu->selecteditem = menu->options->common.next->common.next->common.next;
|
||||
menu->selecteditem = menu->options;
|
||||
//bottoms up!
|
||||
if (r_shadow_realtime_world.ival)
|
||||
item = 1; //realtime
|
||||
else if (r_deluxemapping_cvar.ival)
|
||||
item = 2; //nice
|
||||
else if (gl_load24bit.ival)
|
||||
item = 3; //normal
|
||||
else if (r_softwarebanding_cvar.ival)
|
||||
item = 4;
|
||||
else if (!r_drawflat.ival)
|
||||
item = 5;
|
||||
else
|
||||
item = 6;
|
||||
while (item --> 0)
|
||||
menu->selecteditem = menu->selecteditem->common.next;
|
||||
menu->cursoritem->common.posy = menu->selecteditem->common.posy;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define POLYS
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
#define rand myrand //emscripten's libc is doing a terrible job of this.
|
||||
static int rand(void)
|
||||
{ //ripped from glibc
|
||||
static int state = 0xdeadbeef;
|
||||
int val = ((state * 1103515245) + 12345) & 0x7fffffff;
|
||||
state = val;
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
DODGY,
|
||||
|
||||
|
@ -44,6 +56,7 @@ typedef enum {
|
|||
BLOBEXPLOSION_POINT,
|
||||
LAVASPLASH_POINT,
|
||||
EXPLOSION_POINT,
|
||||
EXPLOSION2_POINT,
|
||||
TELEPORTSPLASH_POINT,
|
||||
MUZZLEFLASH_POINT,
|
||||
|
||||
|
@ -78,7 +91,7 @@ typedef struct cparticle_s
|
|||
#define ABSOLUTE_MIN_PARTICLES 512
|
||||
#define ABSOLUTE_MAX_PARTICLES 8192
|
||||
static int r_numparticles;
|
||||
static cparticle_t *particles, *fte_restrict active_particles, *free_particles;
|
||||
static cparticle_t *particles, *active_particles, *free_particles;
|
||||
extern cvar_t r_part_density, r_part_classic_expgrav;
|
||||
|
||||
static unsigned int particleframe;
|
||||
|
@ -132,6 +145,14 @@ static int PClassic_FindParticleType(const char *name)
|
|||
return LAVASPLASH_POINT;
|
||||
if (!stricmp("te_explosion", name))
|
||||
return EXPLOSION_POINT;
|
||||
if (!strnicmp("te_explosion2_", name, 14))
|
||||
{
|
||||
char *e;
|
||||
int start = strtoul(name+14, &e, 10);
|
||||
int len = strtoul((*e == '_')?e+1:e, &e, 10);
|
||||
if (!*e && start >= 0 && start <= 255 && len >= 0 && len <= 255)
|
||||
return EXPLOSION2_POINT | (start<<8)|(len<<16);
|
||||
}
|
||||
if (!stricmp("te_teleport", name))
|
||||
return TELEPORTSPLASH_POINT;
|
||||
if (!stricmp("te_muzzleflash", name))
|
||||
|
@ -145,7 +166,7 @@ static int PClassic_FindParticleType(const char *name)
|
|||
static qboolean PClassic_Query(int type, int body, char *outstr, int outstrlen)
|
||||
{
|
||||
char *n = NULL;
|
||||
switch(type)
|
||||
switch(type&0xff)
|
||||
{
|
||||
case ROCKET_TRAIL:
|
||||
n = "tr_rocket";
|
||||
|
@ -181,6 +202,9 @@ static qboolean PClassic_Query(int type, int body, char *outstr, int outstrlen)
|
|||
case EXPLOSION_POINT:
|
||||
n = "te_explosion";
|
||||
break;
|
||||
case EXPLOSION2_POINT:
|
||||
n = va("te_explosion2_%i_%i", (type>>8)&0xff, (type>>16)&0xff);
|
||||
break;
|
||||
case TELEPORTSPLASH_POINT:
|
||||
n = "te_teleport";
|
||||
break;
|
||||
|
@ -627,6 +651,34 @@ static void Classic_ParticleExplosion (vec3_t org)
|
|||
}
|
||||
}
|
||||
|
||||
static void Classic_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
|
||||
{
|
||||
int i, j;
|
||||
cparticle_t *p;
|
||||
int colorMod = 0;
|
||||
|
||||
for (i=0; i<512; i++)
|
||||
{
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.3;
|
||||
p->rgb = d_8to24rgbtable[(colorStart + (colorMod % colorLength)) & 255];
|
||||
colorMod++;
|
||||
|
||||
p->type = pt_blob;
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
p->org[j] = org[j] + ((rand()%32)-16);
|
||||
p->vel[j] = (rand()%512)-256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Classic_BlobExplosion (vec3_t org)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -852,7 +904,7 @@ static void Classic_BrightField (vec3_t org)
|
|||
//use the trail state so fast/slow frames keep the correct particle counts on certain every-frame effects
|
||||
static int PClassic_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk)
|
||||
{
|
||||
switch(typenum)
|
||||
switch(typenum&0xff)
|
||||
{
|
||||
case BRIGHTFIELD_POINT:
|
||||
Classic_BrightField(org);
|
||||
|
@ -866,6 +918,9 @@ static int PClassic_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
case EXPLOSION_POINT:
|
||||
Classic_ParticleExplosion(org);
|
||||
break;
|
||||
case EXPLOSION2_POINT:
|
||||
Classic_ParticleExplosion2(org, (typenum>>8)&0xff, (typenum>>16)&0xff);
|
||||
break;
|
||||
case TELEPORTSPLASH_POINT:
|
||||
Classic_TeleportSplash(org);
|
||||
break;
|
||||
|
|
|
@ -29,6 +29,18 @@ The engine has a few builtins.
|
|||
|
||||
#ifdef PSET_SCRIPT
|
||||
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
#define rand myrand //emscripten's libc is doing a terrible job of this.
|
||||
static int rand(void)
|
||||
{ //ripped from glibc
|
||||
static int state = 0xdeadbeef;
|
||||
int val = ((state * 1103515245) + 12345) & 0x7fffffff;
|
||||
state = val;
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GLQUAKE
|
||||
#include "glquake.h"//hack
|
||||
#endif
|
||||
|
@ -55,7 +67,6 @@ extern particleengine_t pe_classic;
|
|||
particleengine_t *fallback = NULL; //does this really need to be 'extern'?
|
||||
#define FALLBACKBIAS 0x1000000
|
||||
|
||||
static int pt_pointfile = P_INVALID;
|
||||
static int pe_default = P_INVALID;
|
||||
static int pe_size2 = P_INVALID;
|
||||
static int pe_size3 = P_INVALID;
|
||||
|
@ -407,7 +418,7 @@ static struct {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
static part_type_t *P_GetParticleType(char *config, char *name)
|
||||
static part_type_t *P_GetParticleType(const char *config, const char *name)
|
||||
{
|
||||
int i;
|
||||
part_type_t *ptype;
|
||||
|
@ -467,19 +478,66 @@ static part_type_t *P_GetParticleType(char *config, char *name)
|
|||
}
|
||||
|
||||
//unconditionally allocates a particle object. this allows out-of-order allocations.
|
||||
static int P_AllocateParticleType(char *config, char *name) //guarentees that the particle type exists, returning it's index.
|
||||
static int P_AllocateParticleType(const char *config, const char *name) //guarentees that the particle type exists, returning it's index.
|
||||
{
|
||||
part_type_t *pt = P_GetParticleType(config, name);
|
||||
return pt - part_type;
|
||||
}
|
||||
|
||||
static void PScript_RetintEffect(part_type_t *to, part_type_t *from, const char *colourcodes)
|
||||
{
|
||||
char name[sizeof(to->name)];
|
||||
char config[sizeof(to->config)];
|
||||
|
||||
Q_strncpyz(name, to->name, sizeof(to->name));
|
||||
Q_strncpyz(config, to->config, sizeof(to->config));
|
||||
|
||||
//'to' was already purged, so we don't need to care about that.
|
||||
memcpy(to, from, sizeof(*to));
|
||||
|
||||
Q_strncpyz(to->name, name, sizeof(to->name));
|
||||
Q_strncpyz(to->config, config, sizeof(to->config));
|
||||
|
||||
//make sure 'to' has its own copy of any lists, so that we don't have issues when freeing this memory again.
|
||||
if (to->models)
|
||||
{
|
||||
to->models = BZ_Malloc(to->nummodels * sizeof(*to->models));
|
||||
memcpy(to->models, from->models, to->nummodels * sizeof(*to->models));
|
||||
}
|
||||
if (to->sounds)
|
||||
{
|
||||
to->sounds = BZ_Malloc(to->numsounds * sizeof(*to->sounds));
|
||||
memcpy(to->sounds, from->sounds, to->numsounds * sizeof(*to->sounds));
|
||||
}
|
||||
if (to->ramp)
|
||||
{
|
||||
to->ramp = BZ_Malloc(to->rampindexes * sizeof(*to->ramp));
|
||||
memcpy(to->ramp, from->ramp, to->rampindexes * sizeof(*to->ramp));
|
||||
}
|
||||
|
||||
//'from' might still have some links so we need to clear those out.
|
||||
to->nexttorun = NULL;
|
||||
to->particles = NULL;
|
||||
to->clippeddecals = NULL;
|
||||
to->beams = NULL;
|
||||
to->skytris = NULL;
|
||||
to->slooks = &to->looks;
|
||||
r_plooksdirty = true;
|
||||
|
||||
to->colorindex = strtoul(colourcodes, (char**)&colourcodes, 10);
|
||||
if (*colourcodes == '_')
|
||||
colourcodes++;
|
||||
to->colorrand = strtoul(colourcodes, (char**)&colourcodes, 10);
|
||||
}
|
||||
|
||||
//public interface. get without creating.
|
||||
static int PScript_FindParticleType(const char *name)
|
||||
static int PScript_FindParticleType(const char *fullname)
|
||||
{
|
||||
int i;
|
||||
part_type_t *ptype = NULL;
|
||||
char cfg[MAX_QPATH];
|
||||
char *dot;
|
||||
const char *name = fullname;
|
||||
dot = strchr(name, '.');
|
||||
if (dot && (dot - name) < MAX_QPATH-1)
|
||||
{
|
||||
|
@ -528,6 +586,16 @@ static int PScript_FindParticleType(const char *name)
|
|||
}
|
||||
if (!ptype || !ptype->loaded)
|
||||
{
|
||||
if (!strnicmp(name, "te_explosion2_", 14))
|
||||
{
|
||||
int from = PScript_FindParticleType(va("%s.te_explosion2", cfg));
|
||||
if (from != P_INVALID)
|
||||
{
|
||||
int to = P_AllocateParticleType(cfg, name);
|
||||
PScript_RetintEffect(&part_type[to], &part_type[from], name+14);
|
||||
return to;
|
||||
}
|
||||
}
|
||||
if (*cfg)
|
||||
P_LoadParticleSet(cfg, true);
|
||||
|
||||
|
@ -2757,13 +2825,6 @@ static qboolean PScript_InitParticles (void)
|
|||
Cmd_AddCommand("r_beaminfo", P_BeamInfo_f);
|
||||
//#endif
|
||||
|
||||
|
||||
pt_pointfile = P_AllocateParticleType("", "PT_POINTFILE");
|
||||
pe_default = P_AllocateParticleType("", "PE_DEFAULT");
|
||||
pe_size2 = P_AllocateParticleType("", "PE_SIZE2");
|
||||
pe_size3 = P_AllocateParticleType("", "PE_SIZE3");
|
||||
pe_defaulttrail = P_AllocateParticleType("", "PE_DEFAULTTRAIL");
|
||||
|
||||
Cvar_Hook(&r_particledesc, R_ParticleDesc_Callback);
|
||||
Cvar_ForceCallback(&r_particledesc);
|
||||
|
||||
|
@ -2811,6 +2872,11 @@ static void PScript_Shutdown (void)
|
|||
Cmd_RemoveCommand("r_beaminfo");
|
||||
#endif
|
||||
|
||||
pe_default = P_INVALID;
|
||||
pe_size2 = P_INVALID;
|
||||
pe_size3 = P_INVALID;
|
||||
pe_defaulttrail = P_INVALID;
|
||||
|
||||
while(loadedconfigs)
|
||||
{
|
||||
pcfg_t *cfg;
|
||||
|
@ -3078,6 +3144,7 @@ static void P_ReadPointFile_f (void)
|
|||
char name[MAX_OSPATH];
|
||||
char line[1024];
|
||||
char *s;
|
||||
int pt_pointfile;
|
||||
|
||||
COM_StripExtension(cl.worldmodel->name, name, sizeof(name));
|
||||
strcat(name, ".pts");
|
||||
|
@ -3093,6 +3160,8 @@ static void P_ReadPointFile_f (void)
|
|||
|
||||
Con_Printf ("Reading %s...\n", name);
|
||||
c = 0;
|
||||
pt_pointfile = PScript_FindParticleType("PT_POINTFILE");
|
||||
if (pt_pointfile != P_INVALID)
|
||||
for ( ;; )
|
||||
{
|
||||
VFS_GETS(f, line, sizeof(line));
|
||||
|
@ -4372,25 +4441,25 @@ static void PScript_RunParticleEffect (vec3_t org, vec3_t dir, int color, int co
|
|||
ptype = P_FindParticleType(va("pe_%i", color));
|
||||
if (P_RunParticleEffectType(org, dir, count, ptype))
|
||||
{
|
||||
if (count > 130 && part_type[pe_size3].loaded)
|
||||
if (count > 130 && pe_size3 != P_INVALID)
|
||||
{
|
||||
part_type[pe_size3].colorindex = color & ~0x7;
|
||||
part_type[pe_size3].colorrand = 8;
|
||||
P_RunParticleEffectType(org, dir, count, pe_size3);
|
||||
}
|
||||
else if (count > 20 && part_type[pe_size2].loaded)
|
||||
else if (count > 20 && pe_size2 != P_INVALID)
|
||||
{
|
||||
part_type[pe_size2].colorindex = color & ~0x7;
|
||||
part_type[pe_size2].colorrand = 8;
|
||||
P_RunParticleEffectType(org, dir, count, pe_size2);
|
||||
}
|
||||
else if (part_type[pe_default].loaded || !fallback)
|
||||
else if (pe_default != P_INVALID)
|
||||
{
|
||||
part_type[pe_default].colorindex = color & ~0x7;
|
||||
part_type[pe_default].colorrand = 8;
|
||||
P_RunParticleEffectType(org, dir, count, pe_default);
|
||||
}
|
||||
else
|
||||
else if (fallback)
|
||||
fallback->RunParticleEffect(org, dir, color, count);
|
||||
}
|
||||
}
|
||||
|
@ -5105,11 +5174,14 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlk
|
|||
}
|
||||
|
||||
static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk)
|
||||
{
|
||||
if (pe_defaulttrail != P_INVALID)
|
||||
{
|
||||
part_type[pe_defaulttrail].colorindex = color;
|
||||
part_type[pe_defaulttrail].colorrand = crnd;
|
||||
P_ParticleTrail(start, end, pe_defaulttrail, 0, NULL, tsk);
|
||||
}
|
||||
}
|
||||
|
||||
static vec3_t pright, pup;
|
||||
static float pframetime;
|
||||
|
@ -5805,6 +5877,12 @@ static void PScript_DrawParticleTypes (void)
|
|||
if (r_plooksdirty)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
pe_default = PScript_FindParticleType("PE_DEFAULT");
|
||||
pe_size2 = PScript_FindParticleType("PE_SIZE2");
|
||||
pe_size3 = PScript_FindParticleType("PE_SIZE3");
|
||||
pe_defaulttrail = PScript_FindParticleType("PE_DEFAULTTRAIL");
|
||||
|
||||
for (i = 0; i < numparticletypes; i++)
|
||||
{
|
||||
//set the fallback
|
||||
|
@ -5938,6 +6016,8 @@ static void PScript_DrawParticleTypes (void)
|
|||
// prediction takes care of the rest
|
||||
switch(type->looks.type)
|
||||
{
|
||||
case PT_INVISIBLE:
|
||||
break;
|
||||
case PT_BEAM:
|
||||
bdraw = GL_DrawParticleBeam;
|
||||
break;
|
||||
|
|
|
@ -2983,15 +2983,14 @@ static void QCBUILTIN PF_cs_getentitytoken (pubprogfuncs_t *prinst, struct globa
|
|||
}
|
||||
else
|
||||
{
|
||||
com_tokentype = TTP_LINEENDING;
|
||||
while(com_tokentype == TTP_LINEENDING)
|
||||
{
|
||||
csqcmapentitydata = COM_ParseToken(csqcmapentitydata, "{}()\'\":,");
|
||||
}
|
||||
char *QCC_COM_Parse (const char *data);
|
||||
extern char qcc_token[];
|
||||
csqcmapentitydata = QCC_COM_Parse(csqcmapentitydata);
|
||||
|
||||
if (!csqcmapentitydata) //hit the end
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
else
|
||||
RETURN_TSTRING(com_token);
|
||||
RETURN_TSTRING(qcc_token);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3757,6 +3756,12 @@ static void QCBUILTIN PF_cl_te_customflash (pubprogfuncs_t *prinst, struct globa
|
|||
|
||||
static void QCBUILTIN PF_cl_te_bloodshower (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *minb = G_VECTOR(OFS_PARM0);
|
||||
float *maxb = G_VECTOR(OFS_PARM1);
|
||||
vec3_t vel = {0,0,-G_FLOAT(OFS_PARM2)};
|
||||
float howmany = G_FLOAT(OFS_PARM3);
|
||||
|
||||
P_RunParticleCube(P_FindParticleType("te_bloodshower"), minb, maxb, vel, vel, howmany, 0, false, 0);
|
||||
}
|
||||
static void QCBUILTIN PF_cl_te_particlecube (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
|
@ -3772,12 +3777,41 @@ static void QCBUILTIN PF_cl_te_particlecube (pubprogfuncs_t *prinst, struct glob
|
|||
}
|
||||
static void QCBUILTIN PF_cl_te_spark (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *pos = G_VECTOR(OFS_PARM0);
|
||||
float *pos2 = G_VECTOR(OFS_PARM1);
|
||||
float cnt = G_FLOAT(OFS_PARM2);
|
||||
P_RunParticleEffectType(pos, pos2, cnt, ptdp_spark);
|
||||
}
|
||||
static void QCBUILTIN PF_cl_te_smallflash (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *pos = G_VECTOR(OFS_PARM0);
|
||||
dlight_t *dl = CL_AllocDlight (0);
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 200;
|
||||
dl->decay = 1000;
|
||||
dl->die = cl.time + 0.2;
|
||||
dl->color[0] = 2.0;
|
||||
dl->color[1] = 2.0;
|
||||
dl->color[2] = 2.0;
|
||||
}
|
||||
static void QCBUILTIN PF_cl_te_explosion2 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *pos = G_VECTOR(OFS_PARM0);
|
||||
int colorStart = G_FLOAT(OFS_PARM1);
|
||||
int colorLength = G_FLOAT(OFS_PARM2);
|
||||
int ef = P_FindParticleType(va("TE_EXPLOSION2_%i_%i", colorStart, colorLength));
|
||||
if (ef == P_INVALID)
|
||||
ef = pt_explosion;
|
||||
P_RunParticleEffectType(pos, NULL, 1, ef);
|
||||
if (r_explosionlight.value)
|
||||
{
|
||||
dlight_t *dl = CL_AllocDlight (0);
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
}
|
||||
S_StartSound (0, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0, 0);
|
||||
}
|
||||
static void QCBUILTIN PF_cl_te_lightning1 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
|
@ -3813,6 +3847,10 @@ static void QCBUILTIN PF_cl_te_beam (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
}
|
||||
static void QCBUILTIN PF_cl_te_plasmaburn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *pos = G_VECTOR(OFS_PARM0);
|
||||
|
||||
if (P_RunParticleEffectType(pos, NULL, 1, P_FindParticleType("te_plasmaburn")))
|
||||
P_RunParticleEffect(pos, vec3_origin, 15, 50);
|
||||
}
|
||||
static void QCBUILTIN PF_cl_te_explosionrgb (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
|
|
|
@ -321,7 +321,7 @@ void Host_InitCommands (void);
|
|||
void Host_Init (quakeparms_t *parms);
|
||||
void Host_FinishInit(void);
|
||||
void Host_Shutdown(void);
|
||||
qboolean com_fatalerror; //supresses shutdown prints+threads
|
||||
qboolean com_workererror; //supresses shutdown prints+threads
|
||||
NORETURN void VARGS Host_Error (char *error, ...) LIKEPRINTF(1);
|
||||
NORETURN void VARGS Host_EndGame (char *message, ...) LIKEPRINTF(1);
|
||||
qboolean Host_SimulationTime(float time);
|
||||
|
|
|
@ -20,7 +20,7 @@ shader_t *shader_crosshair;
|
|||
|
||||
static mpic_t *conback;
|
||||
static mpic_t *draw_backtile;
|
||||
static shader_t *shader_draw_fill, *shader_draw_fill_trans;
|
||||
shader_t *shader_draw_fill, *shader_draw_fill_trans;
|
||||
mpic_t *draw_disc;
|
||||
|
||||
shader_t *shader_contrastup;
|
||||
|
|
|
@ -1593,12 +1593,85 @@ char *particle_set_high =
|
|||
//hide it in nq - WARNING: some mods use this sprite as a flame thrower.
|
||||
//r_effect "progs/s_explod.spr" hidden 1
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
//rogue te_explosion2 effect
|
||||
//note: if not otherwise defined, te_explosion2_BASE_RAND maps to this, and specifies the palette colours.
|
||||
"r_part te_explosion2\n"
|
||||
"{\n"
|
||||
"type texturedspark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 65 31 95 256 8 32\n"
|
||||
"count 256\n"
|
||||
"scale 5\n"
|
||||
"scalefactor 1\n"
|
||||
"scaledelta -15\n"
|
||||
"alpha 0.2\n"
|
||||
"die 0.5\n"
|
||||
"blend add\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 1\n"
|
||||
"randomvel 1000\n"
|
||||
"friction 0.01\n"
|
||||
"gravity 100\n"
|
||||
"stretchfactor -80\n"
|
||||
"}\n"
|
||||
//dragon fireball
|
||||
//r_part te_explosion2_228_5
|
||||
|
||||
//rogue multigrenade sub explosion
|
||||
//also triggered from a shielded rogue player touching another player (and doing some damage)
|
||||
//also used during the ending.
|
||||
//red particles
|
||||
//r_part te_explosion2_230_5
|
||||
|
||||
//rogue plasma explosion
|
||||
//also rogue timemachine explosion
|
||||
//white particles splaying outwards
|
||||
//r_part te_explosion2_244_3
|
||||
|
||||
//////////////////////////////////////////
|
||||
//for when a spawn dies.
|
||||
//also used by TF for emp explosions.
|
||||
//r_part te_tarexplosion
|
||||
//{
|
||||
//}
|
||||
"r_part te_tarexplosion\n"
|
||||
"{\n"
|
||||
"type texturedspark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 65 31 95 256 8 32\n"
|
||||
"count 128\n"
|
||||
"scale 5\n"
|
||||
"scalefactor 1\n"
|
||||
"scaledelta -15\n"
|
||||
"rgb 0 0 17\n"
|
||||
"alpha 0.5\n"
|
||||
"die 0.5\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 1\n"
|
||||
"randomvel 500\n"
|
||||
"friction 0.01\n"
|
||||
"gravity 100\n"
|
||||
"stretchfactor -80\n"
|
||||
"}\n"
|
||||
"r_part +te_tarexplosion\n"
|
||||
"{\n"
|
||||
"type texturedspark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 65 31 95 256 8 32\n"
|
||||
"count 256\n"
|
||||
"scale 5\n"
|
||||
"scalefactor 1\n"
|
||||
"scaledelta -15\n"
|
||||
"rgb 83 67 115\n"
|
||||
"alpha 0.3\n"
|
||||
"die 0.5\n"
|
||||
"blend add\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 1\n"
|
||||
"randomvel 500\n"
|
||||
"friction 0.01\n"
|
||||
"gravity 100\n"
|
||||
"stretchfactor -80\n"
|
||||
"}\n"
|
||||
|
||||
//////////////////////////////////////////
|
||||
//cthon falling into lava.
|
||||
|
@ -1742,6 +1815,8 @@ char *particle_set_high =
|
|||
//rygel's pack sucks
|
||||
"r_trail \"progs/v_spike.mdl\" tr_vorespike\n"
|
||||
|
||||
|
||||
////////////////////
|
||||
//enforcer laser effect
|
||||
"r_part tr_enforcerlaser\n"
|
||||
"{\n"
|
||||
|
@ -1769,6 +1844,79 @@ char *particle_set_high =
|
|||
"}\n"
|
||||
"r_trail \"progs/laser.mdl\" tr_enforcerlaser\n"
|
||||
|
||||
/////////////////////////////////////////
|
||||
//rogue wrath enemy's projectiles
|
||||
"r_part tr_wrathball\n"
|
||||
"{\n"
|
||||
"type texturedspark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 97 95 191 256\n"
|
||||
"scale 15\n"
|
||||
"step 4\n"
|
||||
"alpha 0.3\n"
|
||||
"die 0.5\n"
|
||||
"rgb 255 0 0\n"
|
||||
"veladd -32\n"
|
||||
"spawnmode spiral\n"
|
||||
"spawnvel 16\n"
|
||||
"randomvel 32\n"
|
||||
"friction 0\n"
|
||||
"scalefactor 1\n"
|
||||
"blend add\n"
|
||||
"lighttime 0.2\n"
|
||||
"lightshadows 0\n"
|
||||
"lightradius 150\n"
|
||||
"lightrgb 1 0.27 0\n"
|
||||
"lightrgbfade 5 1 0\n"
|
||||
"lightcorona 2 0.5\n"
|
||||
"}\n"
|
||||
"r_trail \"progs/w_ball.mdl\" tr_wrathball\n"
|
||||
|
||||
//wrath death
|
||||
//grey particles
|
||||
//no difference from the fallback except for the blend mode. this should ensure that we are not quite so invisible.
|
||||
"r_part te_explosion2_0_4\n"
|
||||
"{\n"
|
||||
"type texturedspark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 65 31 95 256 8 32\n"
|
||||
"count 256\n"
|
||||
"scale 5\n"
|
||||
"scalefactor 1\n"
|
||||
"scaledelta -15\n"
|
||||
"alpha 0.2\n"
|
||||
"die 0.5\n"
|
||||
"spawnmode ball\n"
|
||||
"spawnorg 1\n"
|
||||
"randomvel 1000\n"
|
||||
"friction 0.01\n"
|
||||
"gravity 100\n"
|
||||
"stretchfactor -80\n"
|
||||
"}\n"
|
||||
|
||||
/////////////////////////////////////////
|
||||
//rogue lavaspikes
|
||||
"r_part tr_lavaspike\n"
|
||||
"{\n"
|
||||
"type spark\n"
|
||||
"texture \"particles/fteparticlefont.tga\"\n"
|
||||
"tcoords 1 97 95 191 256\n"
|
||||
"scale 15\n"
|
||||
"step 4\n"
|
||||
"alpha 0.3\n"
|
||||
"die 0.5\n"
|
||||
"rgb 255 0 0\n"
|
||||
"veladd -32\n"
|
||||
"spawnmode spiral\n"
|
||||
"spawnvel 16\n"
|
||||
"randomvel 32\n"
|
||||
"friction 0\n"
|
||||
"scalefactor 1\n"
|
||||
"blend add\n"
|
||||
"}\n"
|
||||
"r_trail \"progs/lspike.mdl\" tr_lavaspike\n"
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
//scrag missiles.
|
||||
"r_part tr_wizspike\n"
|
||||
|
|
|
@ -256,19 +256,23 @@ extern cvar_t r_novis;
|
|||
extern cvar_t r_speeds;
|
||||
extern cvar_t r_waterwarp;
|
||||
|
||||
#ifdef ANDROID
|
||||
#if defined(ANDROID)
|
||||
//on android, these numbers seem to be generating major weirdness, so disable these.
|
||||
cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0");
|
||||
cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "0");
|
||||
cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0");
|
||||
cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "0");
|
||||
#elif defined(FTE_TARGET_WEB)
|
||||
//on firefox (but not chrome or ie), these numbers seem to be generating major weirdness, so tone them down significantly by default.
|
||||
cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0.05");
|
||||
cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "1");
|
||||
#else
|
||||
cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0.05");
|
||||
cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "25");
|
||||
cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0.05");
|
||||
cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "25");
|
||||
#endif
|
||||
cvar_t r_polygonoffset_shadowmap_offset = SCVAR("r_polygonoffset_shadowmap_factor", "0.05");
|
||||
cvar_t r_polygonoffset_shadowmap_factor = SCVAR("r_polygonoffset_shadowmap_offset", "0");
|
||||
cvar_t r_polygonoffset_shadowmap_offset = CVAR("r_polygonoffset_shadowmap_factor", "0.05");
|
||||
cvar_t r_polygonoffset_shadowmap_factor = CVAR("r_polygonoffset_shadowmap_offset", "0");
|
||||
|
||||
cvar_t r_polygonoffset_stencil_factor = SCVAR("r_polygonoffset_stencil_factor", "0.01");
|
||||
cvar_t r_polygonoffset_stencil_offset = SCVAR("r_polygonoffset_stencil_offset", "1");
|
||||
cvar_t r_polygonoffset_stencil_factor = CVAR("r_polygonoffset_stencil_factor", "0.01");
|
||||
cvar_t r_polygonoffset_stencil_offset = CVAR("r_polygonoffset_stencil_offset", "1");
|
||||
|
||||
rendererstate_t currentrendererstate;
|
||||
|
||||
|
|
|
@ -1613,6 +1613,7 @@ void Sbar_DrawInventory (playerview_t *pv)
|
|||
qboolean headsup;
|
||||
qboolean hudswap;
|
||||
float wleft, wtop;
|
||||
apic_t *ibar;
|
||||
|
||||
headsup = !(cl_sbar.value || (scr_viewsize.value<100&&cl.splitclients==1));
|
||||
hudswap = cl_hudswap.value; // Get that nasty float out :)
|
||||
|
@ -1623,18 +1624,19 @@ void Sbar_DrawInventory (playerview_t *pv)
|
|||
if (sbar_hipnotic)
|
||||
wtop -= 16*2;
|
||||
|
||||
if (!headsup)
|
||||
{
|
||||
if (sbar_rogue)
|
||||
{
|
||||
if ( pv->stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
|
||||
Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[0]);
|
||||
ibar = rsb_invbar[0];
|
||||
else
|
||||
Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[1]);
|
||||
ibar = rsb_invbar[1];
|
||||
}
|
||||
else
|
||||
Sbar_DrawPic (0, -24, 320, 24, sb_ibar);
|
||||
}
|
||||
ibar = sb_ibar;
|
||||
|
||||
if (!headsup)
|
||||
Sbar_DrawPic (0, -24, 320, 24, ibar);
|
||||
|
||||
// weapons
|
||||
for (i=0 ; i<7 ; i++)
|
||||
{
|
||||
|
@ -1825,22 +1827,23 @@ void Sbar_DrawInventory (playerview_t *pv)
|
|||
if (headsup)
|
||||
{
|
||||
for (i=0 ; i<4 ; i++)
|
||||
Sbar_DrawSubPic((hudswap) ? sbar_rect_left : (sbar_rect.width-42), -24 - (4-i)*11, 42, 11, sb_ibar, 3+(i*48), 0, 320, 24);
|
||||
Sbar_DrawSubPic((hudswap) ? sbar_rect_left : (sbar_rect.width-42), -24 - (4-i)*11, 42, 11, ibar, 3+(i*48), 0, 320, 24);
|
||||
}
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
snprintf (num, sizeof(num), "%3i", pv->stats[STAT_SHELLS+i] );
|
||||
snprintf (num, sizeof(num), "%4i", pv->stats[STAT_SHELLS+i] );
|
||||
numc[0] = CON_WHITEMASK|0xe000|((num[0]!=' ')?(num[0] + 18-'0'):' ');
|
||||
numc[1] = CON_WHITEMASK|0xe000|((num[1]!=' ')?(num[1] + 18-'0'):' ');
|
||||
numc[2] = CON_WHITEMASK|0xe000|((num[2]!=' ')?(num[2] + 18-'0'):' ');
|
||||
numc[3] = 0;
|
||||
numc[3] = CON_WHITEMASK|0xe000|((num[3]!=' ')?(num[3] + 18-'0'):' ');
|
||||
numc[4] = 0;
|
||||
if (headsup)
|
||||
{
|
||||
Sbar_DrawExpandedString((hudswap) ? sbar_rect_left+3 : (sbar_rect.width-39), -24 - (4-i)*11, numc);
|
||||
Sbar_DrawExpandedString(((hudswap) ? sbar_rect_left+3 : (sbar_rect.width-39)) - 4, -24 - (4-i)*11, numc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sbar_DrawExpandedString((6*i+1)*8 - 2, -24, numc);
|
||||
Sbar_DrawExpandedString((6*i+1)*8 - 2 - 4, -24, numc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -777,7 +777,7 @@ static qboolean OpenAL_InitLibrary(void)
|
|||
#if FTE_TARGET_WEB
|
||||
firefoxstaticsounds = !!strstr(emscripten_run_script_string("navigator.userAgent"), "Firefox");
|
||||
if (firefoxstaticsounds)
|
||||
Con_Printf("Firefox detected - disabling static sounds to avoid SORRY, I CAN'T HEAR YOU\n");
|
||||
Con_DPrintf("Firefox detected - disabling static sounds to avoid SORRY, I CAN'T HEAR YOU\n");
|
||||
#endif
|
||||
|
||||
#ifdef OPENAL_STATIC
|
||||
|
|
|
@ -4721,7 +4721,7 @@ static void *com_workercondition[WORKERTHREADS];
|
|||
static qboolean com_workerdone[WORKERTHREADS];
|
||||
static void *com_workerthread[WORKERTHREADS];
|
||||
static unsigned int mainthreadid;
|
||||
qboolean com_fatalerror;
|
||||
qboolean com_workererror;
|
||||
static struct com_work_s
|
||||
{
|
||||
struct com_work_s *next;
|
||||
|
@ -4739,9 +4739,9 @@ void COM_WorkerAbort(char *message)
|
|||
{
|
||||
int us;
|
||||
struct com_work_s work;
|
||||
com_fatalerror = true;
|
||||
if (Sys_IsMainThread())
|
||||
return;
|
||||
com_workererror = true;
|
||||
|
||||
if (!com_workercondition[0])
|
||||
return; //Sys_IsMainThread was probably called too early...
|
||||
|
@ -4813,7 +4813,7 @@ void COM_AddWork(int thread, void(*func)(void *ctx, void *data, size_t a, size_t
|
|||
struct com_work_s *work;
|
||||
|
||||
//no worker there, just do it immediately on this thread instead of pushing it to the worker.
|
||||
if (thread && (!com_workerthread[thread] || com_fatalerror))
|
||||
if (thread && (!com_workerthread[thread] || com_workererror))
|
||||
{
|
||||
func(ctx, data, a, b);
|
||||
return;
|
||||
|
@ -4928,7 +4928,7 @@ void COM_DestroyWorkerThread(void)
|
|||
{
|
||||
int i;
|
||||
COM_WorkerFullSync();
|
||||
com_fatalerror = false;
|
||||
// com_workererror = false;
|
||||
for (i = 0; i < WORKERTHREADS; i++)
|
||||
{
|
||||
if (com_workerthread[i])
|
||||
|
@ -4942,7 +4942,7 @@ void COM_DestroyWorkerThread(void)
|
|||
Sys_LockConditional(com_workercondition[0]);
|
||||
do
|
||||
{
|
||||
if (com_fatalerror)
|
||||
if (com_workererror)
|
||||
break;
|
||||
while(COM_DoWork(0, true))
|
||||
;
|
||||
|
@ -4995,7 +4995,7 @@ void COM_WorkerFullSync(void)
|
|||
Sys_LockConditional(com_workercondition[0]);
|
||||
do
|
||||
{
|
||||
if (com_fatalerror)
|
||||
if (com_workererror)
|
||||
break;
|
||||
while(COM_DoWork(0, true))
|
||||
cmds++;
|
||||
|
@ -5003,7 +5003,7 @@ void COM_WorkerFullSync(void)
|
|||
break;
|
||||
} while (Sys_ConditionWait(com_workercondition[0]));
|
||||
Sys_UnlockConditional(com_workercondition[0]);
|
||||
if (com_fatalerror)
|
||||
if (com_workererror)
|
||||
break;
|
||||
if (cmds > 1)
|
||||
repeat = true;
|
||||
|
@ -5064,7 +5064,7 @@ void COM_WorkerPartialSync(void *priorityctx, int *address, int value)
|
|||
Sys_LockConditional(com_workercondition[0]);
|
||||
do
|
||||
{
|
||||
if (com_fatalerror)
|
||||
if (com_workererror)
|
||||
break;
|
||||
while(COM_DoWork(0, true))
|
||||
{
|
||||
|
|
|
@ -489,6 +489,7 @@ void COM_WriteFile (const char *filename, enum fs_relative fsroot, const void *d
|
|||
void FS_FlushFSHashReally(qboolean domutexes);
|
||||
void FS_FlushFSHashWritten(void);
|
||||
void FS_FlushFSHashRemoved(void);
|
||||
void FS_FlushFSHash(void);
|
||||
void FS_CreatePath(const char *pname, enum fs_relative relativeto);
|
||||
qboolean FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto); //0 on success, non-0 on error
|
||||
qboolean FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto);
|
||||
|
|
|
@ -828,6 +828,10 @@ void FS_FlushFSHashRemoved(void)
|
|||
{
|
||||
FS_FlushFSHashReally(true);
|
||||
}
|
||||
void FS_FlushFSHash(void)
|
||||
{
|
||||
FS_FlushFSHashReally(true);
|
||||
}
|
||||
|
||||
static void QDECL FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)
|
||||
{
|
||||
|
@ -4377,11 +4381,20 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
qboolean builtingame = false;
|
||||
flocation_t loc;
|
||||
|
||||
char *vidfile[] = {"gfx.wad", "gfx/conback.lmp"};
|
||||
searchpathfuncs_t *vidpath[countof(vidfile)];
|
||||
|
||||
//if any of these files change location, the configs will be re-execed.
|
||||
//note that we reuse path handles if they're still valid, so we can just check the pointer to see if it got unloaded/replaced.
|
||||
char *conffile[] = {"quake.rc", "hexen.rc", "default.cfg", "server.cfg", NULL};
|
||||
searchpathfuncs_t *confpath[sizeof(conffile)/sizeof(conffile[0])];
|
||||
for (i = 0; conffile[i]; i++)
|
||||
char *conffile[] = {"quake.rc", "hexen.rc", "default.cfg", "server.cfg"};
|
||||
searchpathfuncs_t *confpath[countof(conffile)];
|
||||
|
||||
for (i = 0; i < countof(vidfile); i++)
|
||||
{
|
||||
FS_FLocateFile(vidfile[i], FSLFRT_IFFOUND, &loc); //q1
|
||||
vidpath[i] = loc.search?loc.search->handle:NULL;
|
||||
}
|
||||
for (i = 0; i < countof(conffile); i++)
|
||||
{
|
||||
FS_FLocateFile(conffile[i], FSLFRT_IFFOUND, &loc); //q1
|
||||
confpath[i] = loc.search?loc.search->handle:NULL;
|
||||
|
@ -4552,7 +4565,22 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
|
||||
if (allowreloadconfigs)
|
||||
{
|
||||
for (i = 0; conffile[i]; i++)
|
||||
qboolean vidrestart = false;
|
||||
|
||||
if (qrenderer != QR_NONE)
|
||||
{
|
||||
for (i = 0; i < countof(vidfile); i++)
|
||||
{
|
||||
FS_FLocateFile(vidfile[i], FSLFRT_IFFOUND, &loc);
|
||||
if (vidpath[i] != (loc.search?loc.search->handle:NULL))
|
||||
{
|
||||
vidrestart = true;
|
||||
Con_DPrintf("Restarting video because %s has changed\n", vidfile[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < countof(conffile); i++)
|
||||
{
|
||||
FS_FLocateFile(conffile[i], FSLFRT_IFFOUND, &loc);
|
||||
if (confpath[i] != (loc.search?loc.search->handle:NULL))
|
||||
|
@ -4583,6 +4611,10 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef SERVERONLY
|
||||
else if (vidrestart)
|
||||
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
//rebuild the cache now, should be safe to waste some cycles on it
|
||||
|
|
|
@ -2037,7 +2037,7 @@ void CMod_LoadEntityString (model_t *mod, qbyte *mod_base, lump_t *l)
|
|||
// if (l->filelen > MAX_Q2MAP_ENTSTRING)
|
||||
// Host_Error ("Map has too large entity lump");
|
||||
|
||||
mod->entities = ZG_Malloc(&mod->memgroup, l->filelen+1);
|
||||
mod->entities = Z_Malloc(l->filelen+1);
|
||||
memcpy (mod->entities, mod_base + l->fileofs, l->filelen);
|
||||
}
|
||||
|
||||
|
|
|
@ -1782,7 +1782,7 @@ void Plug_Close(plugin_t *plug)
|
|||
prev->next = plug->next;
|
||||
}
|
||||
|
||||
if (!com_fatalerror)
|
||||
if (!com_workererror)
|
||||
Con_DPrintf("Closing plugin %s\n", plug->name);
|
||||
|
||||
//ensure any active contexts provided by the plugin are closed (stuff with destroy callbacks)
|
||||
|
|
|
@ -808,7 +808,13 @@ void PM_AirMove (void)
|
|||
// add gravity
|
||||
VectorMA(pmove.velocity, movevars.entgravity * movevars.gravity * frametime, pmove.gravitydir, pmove.velocity);
|
||||
|
||||
if (movevars.airstep)
|
||||
if (DotProduct(pmove.velocity,pmove.velocity) > 1000*1000)
|
||||
{
|
||||
//when in a windtunnel, step up from where we are rather than the actual ground in order to more closely match nq.
|
||||
//this is needed for r1m5 (770 800 192), just beyond the silver key door.
|
||||
blocked = PM_StepSlideMove (false);
|
||||
}
|
||||
else if (movevars.airstep)
|
||||
blocked = PM_StepSlideMove (true);
|
||||
else
|
||||
blocked = PM_SlideMove ();
|
||||
|
|
|
@ -1645,7 +1645,7 @@ void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
int flags = (prinst->callargc>3)?G_FLOAT(OFS_PARM3):0;
|
||||
int type = flags & 0xff;
|
||||
pf_hashentry_t *ent = NULL;
|
||||
if (tab)
|
||||
if (tab && *name) //our hash tables can't cope with empty keys.
|
||||
{
|
||||
if (!type)
|
||||
type = tab->defaulttype;
|
||||
|
@ -1658,6 +1658,7 @@ void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
BZ_Free(ent);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ev_string)
|
||||
{ //strings copy their value out.
|
||||
const char *value = PR_GetStringOfs(prinst, OFS_PARM2);
|
||||
|
@ -1667,7 +1668,8 @@ void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
ent->name = (char*)(ent+1);
|
||||
ent->type = ev_string;
|
||||
ent->stringdata = ent->name+(nlen+1);
|
||||
memcpy(ent->name, name, nlen+1);
|
||||
memcpy(ent->name, name, nlen);
|
||||
ent->name[nlen] = 0;
|
||||
memcpy(ent->stringdata, value, vlen+1);
|
||||
Hash_Add(&tab->tab, ent->name, ent, &ent->buck);
|
||||
}
|
||||
|
@ -1677,7 +1679,8 @@ void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
ent = BZ_Malloc(sizeof(*ent) + nlen + 1);
|
||||
ent->name = (char*)(ent+1);
|
||||
ent->type = type;
|
||||
memcpy(ent->name, name, nlen+1);
|
||||
memcpy(ent->name, name, nlen);
|
||||
ent->name[nlen] = 0;
|
||||
memcpy(ent->data, data, sizeof(vec3_t));
|
||||
Hash_Add(&tab->tab, ent->name, ent, &ent->buck);
|
||||
}
|
||||
|
@ -4058,7 +4061,7 @@ void QCBUILTIN PF_uri_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
const unsigned char *url = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||
float id = G_FLOAT(OFS_PARM1);
|
||||
const char *mimetype = (prinst->callargc >= 3)?PR_GetStringOfs(prinst, OFS_PARM2):"";
|
||||
const char *dataorsep = PR_GetStringOfs(prinst, OFS_PARM3);
|
||||
const char *dataorsep = (prinst->callargc >= 4)?PR_GetStringOfs(prinst, OFS_PARM3):"";
|
||||
int strbufid = (prinst->callargc >= 5)?G_FLOAT(OFS_PARM4):0;
|
||||
//float cryptokey = (prinst->callargc >= 5)?G_FLOAT(OFS_PARM5):0; //DP feature, not supported in FTE.
|
||||
|
||||
|
@ -5865,7 +5868,9 @@ lh_extension_t QSG_Extensions[] = {
|
|||
{"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}},
|
||||
{"FTE_CSQC_ALTCONSOLES_WIP", 4, NULL, {"con_getset", "con_printf", "con_draw", "con_input"}},
|
||||
{"FTE_CSQC_BASEFRAME", 0, NULL, {NULL}, "Specifies that .basebone, .baseframe, .baselerpfrac, etc exist. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations."},
|
||||
#ifdef HALFLIFEMODELS
|
||||
{"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control
|
||||
#endif
|
||||
{"FTE_CSQC_SERVERBROWSER", 12, NULL, { "gethostcachevalue", "gethostcachestring", "resethostcachemasks", "sethostcachemaskstring", "sethostcachemasknumber",
|
||||
"resorthostcache", "sethostcachesort", "refreshhostcache", "gethostcachenumber", "gethostcacheindexforkey",
|
||||
"addwantedhostcachekey", "getextresponse"}}, //normally only available to the menu. this also adds them to csqc.
|
||||
|
|
|
@ -740,6 +740,11 @@ enum terrainedit_e
|
|||
ter_tex_replace, //vector pos, float radius, string texname
|
||||
ter_reset, //vector pos, float radius
|
||||
ter_reloadsect, //vector pos, float radius
|
||||
|
||||
ter_ents_wipe, //none
|
||||
ter_ents_concat, //string
|
||||
ter_ents_get, //none
|
||||
|
||||
// ter_poly_add, //add a poly, woo
|
||||
// ter_poly_remove, //remove polys
|
||||
|
||||
|
|
|
@ -842,7 +842,7 @@ enum {
|
|||
TE_SPIKE = 0,
|
||||
TE_SUPERSPIKE = 1,
|
||||
TE_GUNSHOT = 2,
|
||||
TE_EXPLOSION = 3,
|
||||
TE_EXPLOSION = 3, //remapped to TEQW_EXPLOSIONNOSPRITE for nq.
|
||||
TE_TAREXPLOSION = 4,
|
||||
TE_LIGHTNING1 = 5,
|
||||
TE_LIGHTNING2 = 6,
|
||||
|
@ -865,7 +865,7 @@ enum {
|
|||
TE_RAILTRAIL = 17, //use the builtin, luke.
|
||||
TEQW_BEAM = 18, //use the builtin, luke.
|
||||
TEQW_EXPLOSION2 = 19, //use the builtin, luke.
|
||||
TE_EXPLOSIONNOSPRITE = 20, //use the builtin, luke.
|
||||
TEQW_EXPLOSIONNOSPRITE = 20,
|
||||
|
||||
// hexen 2
|
||||
TEH2_STREAM_LIGHTNING_SMALL = 24,
|
||||
|
|
|
@ -59,6 +59,30 @@
|
|||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\web\fs_web.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\web\ftejslib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\web\ftejslib.js"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\web\gl_vidweb.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\web\prejs.js"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\web\sys_web.c"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
|
@ -41,6 +41,7 @@ cluster:
|
|||
*/
|
||||
|
||||
int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe);
|
||||
static size_t Terr_GenerateBrushFace(vecV_t *points, size_t maxpoints, vec4_t *planes, size_t numplanes, vec4_t face);
|
||||
|
||||
#define MAXCLUSTERS 64
|
||||
#define MAXSECTIONS 64 //this many sections within each cluster in each direction
|
||||
|
@ -170,6 +171,23 @@ struct hmwater_s
|
|||
shader_t *shader;
|
||||
qbyte holes[8];
|
||||
float heights[9*9];
|
||||
|
||||
/*
|
||||
qboolean facesdown;
|
||||
unsigned int contentmask;
|
||||
float heights[SECTHEIGHTSIZE*SECTHEIGHTSIZE];
|
||||
#ifndef SERVERONLY
|
||||
byte_vec4_t colours[SECTHEIGHTSIZE*SECTHEIGHTSIZE];
|
||||
char texname[4][MAX_QPATH];
|
||||
int lightmap;
|
||||
int lmx, lmy;
|
||||
|
||||
texnums_t textures;
|
||||
vbo_t vbo;
|
||||
mesh_t mesh;
|
||||
mesh_t *amesh;
|
||||
#endif
|
||||
*/
|
||||
};
|
||||
enum
|
||||
{
|
||||
|
@ -193,6 +211,7 @@ typedef struct
|
|||
float minh, maxh;
|
||||
struct heightmap_s *hmmod;
|
||||
|
||||
//FIXME: make layers, each with their own holes+heights+contents+textures+shader+mixes. water will presumably have specific values set for each part.
|
||||
struct hmwater_s *water;
|
||||
|
||||
size_t traceseq;
|
||||
|
@ -315,7 +334,7 @@ typedef struct heightmap_s
|
|||
size_t drawnframe; //don't add it to the scene multiple times.
|
||||
size_t traceseq; //don't trace through this entity multiple times if its in different sections.
|
||||
int refs; //entity is free/reusable when its no longer referenced by any sections
|
||||
entity_t ent;
|
||||
entity_t ent; //note: only model+modelmatrix info is relevant. fixme: implement instancing.
|
||||
|
||||
struct hmentity_s *next; //used for freeing/allocating an entity
|
||||
} *entities;
|
||||
|
@ -772,6 +791,9 @@ static void Terr_AddMesh(heightmap_t *hm, int loadflags, model_t *mod, vec3_t ep
|
|||
e->ent.drawflags = SCALE_ORIGIN_ORIGIN;
|
||||
e->ent.scale = scale;
|
||||
e->ent.playerindex = -1;
|
||||
e->ent.framestate.g[FS_REG].lerpweight[0] = 1;
|
||||
e->ent.topcolour = TOP_DEFAULT;
|
||||
e->ent.bottomcolour = BOTTOM_DEFAULT;
|
||||
e->ent.shaderRGBAf[0] = 1;
|
||||
e->ent.shaderRGBAf[1] = 1;
|
||||
e->ent.shaderRGBAf[2] = 1;
|
||||
|
@ -3164,6 +3186,19 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
|
|||
tdibctx.wmodel = e->model;
|
||||
tdibctx.pvs = (e->model == cl.worldmodel)?frustumvis:NULL;
|
||||
Terr_DrawInBounds(&tdibctx, bounds[0], bounds[2], bounds[1]-bounds[0], bounds[3]-bounds[2]);
|
||||
|
||||
|
||||
/*{
|
||||
trace_t trace;
|
||||
vec3_t player_mins = {-16, -16, -24};
|
||||
vec3_t player_maxs = {16, 16, 32};
|
||||
vec3_t start, end;
|
||||
VectorCopy(cl.playerview[0].simorg, start);
|
||||
VectorCopy(start, end);
|
||||
start[0] += 5;
|
||||
end[2] -= 100;
|
||||
Heightmap_Trace(cl.worldmodel, 0, 0, NULL, start, end, player_mins, player_maxs, false, ~0, &trace);
|
||||
}*/
|
||||
}
|
||||
|
||||
void Terrain_ClipDecal(fragmentdecal_t *dec, float *center, float radius, model_t *model)
|
||||
|
@ -3460,6 +3495,8 @@ typedef struct {
|
|||
vec3_t maxs;
|
||||
vec3_t absmins;
|
||||
vec3_t absmaxs;
|
||||
vec3_t up;
|
||||
vec3_t capsulesize;
|
||||
enum {ispoint, iscapsule, isbox} shape;
|
||||
float frac;
|
||||
float htilesize;
|
||||
|
@ -3467,6 +3504,10 @@ typedef struct {
|
|||
int contents;
|
||||
int hitcontentsmask;
|
||||
trace_t *result;
|
||||
|
||||
#ifdef _DEBUG
|
||||
qboolean debug;
|
||||
#endif
|
||||
} hmtrace_t;
|
||||
|
||||
static int Heightmap_Trace_Brush(hmtrace_t *tr, vec4_t *planes, int numplanes)
|
||||
|
@ -3503,7 +3544,11 @@ static int Heightmap_Trace_Brush(hmtrace_t *tr, vec4_t *planes, int numplanes)
|
|||
dist = DotProduct (ofs, planes[i]);
|
||||
dist = planes[i][3] - dist;
|
||||
break;
|
||||
// capsuledist(dist,plane,mins,maxs)
|
||||
case iscapsule:
|
||||
dist = DotProduct(tr->up, planes[i]);
|
||||
dist = dist*(tr->capsulesize[(dist<0)?1:2]) - tr->capsulesize[0];
|
||||
dist = planes[i][3] - dist;
|
||||
break;
|
||||
case ispoint: // special point case
|
||||
dist = planes[i][3];
|
||||
break;
|
||||
|
@ -3548,6 +3593,57 @@ static int Heightmap_Trace_Brush(hmtrace_t *tr, vec4_t *planes, int numplanes)
|
|||
|
||||
if (!startout)
|
||||
{
|
||||
|
||||
#if 0//def _DEBUG
|
||||
if (tr->debug)
|
||||
{
|
||||
vecV_t facepoints[256];
|
||||
unsigned int numpoints;
|
||||
|
||||
for (i = 0; i < numplanes; i++)
|
||||
{
|
||||
scenetris_t *t;
|
||||
extern shader_t *shader_draw_fill;
|
||||
//generate points now (so we know the correct mins+maxs for the brush, and whether the plane is relevent)
|
||||
numpoints = Terr_GenerateBrushFace(facepoints, countof(facepoints), planes, numplanes, planes[i]);
|
||||
|
||||
|
||||
if (cl_numstrisvert+numpoints > cl_maxstrisvert)
|
||||
break;
|
||||
if (cl_numstrisidx+(numpoints-2)*3 > cl_maxstrisidx)
|
||||
break;
|
||||
|
||||
if (cl_numstris == cl_maxstris)
|
||||
{
|
||||
cl_maxstris+=8;
|
||||
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
|
||||
}
|
||||
t = &cl_stris[cl_numstris++];
|
||||
t->shader = shader_draw_fill;
|
||||
t->flags = 0;
|
||||
t->firstidx = cl_numstrisidx;
|
||||
t->firstvert = cl_numstrisvert;
|
||||
for (j = 2; j < numpoints; j++)
|
||||
{
|
||||
cl_strisidx[cl_numstrisidx++] = 0;
|
||||
cl_strisidx[cl_numstrisidx++] = j-1;
|
||||
cl_strisidx[cl_numstrisidx++] = j;
|
||||
}
|
||||
for (j = 0; j < numpoints; j++)
|
||||
{
|
||||
VectorCopy(facepoints[j], cl_strisvertv[cl_numstrisvert]);
|
||||
cl_strisvertv[cl_numstrisvert][2] += 1;
|
||||
Vector4Set(cl_strisvertc[cl_numstrisvert], 1, 0, 0, 0.2);
|
||||
Vector2Set(cl_strisvertt[cl_numstrisvert], 0, 0);
|
||||
cl_numstrisvert++;
|
||||
}
|
||||
t->numidx = cl_numstrisidx - t->firstidx;
|
||||
t->numvert = cl_numstrisvert-t->firstvert;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
tr->frac = -1;
|
||||
return false;
|
||||
}
|
||||
|
@ -3561,6 +3657,58 @@ static int Heightmap_Trace_Brush(hmtrace_t *tr, vec4_t *planes, int numplanes)
|
|||
tr->frac = nearfrac;//enterfrac;
|
||||
tr->plane[3] = enterdist;
|
||||
VectorCopy(enterplane, tr->plane);
|
||||
|
||||
|
||||
#if 0//def _DEBUG
|
||||
if (tr->debug)
|
||||
{
|
||||
vecV_t facepoints[256];
|
||||
unsigned int numpoints;
|
||||
|
||||
for (i = 0; i < numplanes; i++)
|
||||
{
|
||||
scenetris_t *t;
|
||||
extern shader_t *shader_draw_fill;
|
||||
//generate points now (so we know the correct mins+maxs for the brush, and whether the plane is relevent)
|
||||
numpoints = Terr_GenerateBrushFace(facepoints, countof(facepoints), planes, numplanes, planes[i]);
|
||||
|
||||
|
||||
if (cl_numstrisvert+numpoints > cl_maxstrisvert)
|
||||
break;
|
||||
if (cl_numstrisidx+(numpoints-2)*3 > cl_maxstrisidx)
|
||||
break;
|
||||
|
||||
if (cl_numstris == cl_maxstris)
|
||||
{
|
||||
cl_maxstris+=8;
|
||||
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
|
||||
}
|
||||
t = &cl_stris[cl_numstris++];
|
||||
t->shader = shader_draw_fill;
|
||||
t->flags = 0;
|
||||
t->firstidx = cl_numstrisidx;
|
||||
t->firstvert = cl_numstrisvert;
|
||||
for (j = 2; j < numpoints; j++)
|
||||
{
|
||||
cl_strisidx[cl_numstrisidx++] = 0;
|
||||
cl_strisidx[cl_numstrisidx++] = j-1;
|
||||
cl_strisidx[cl_numstrisidx++] = j;
|
||||
}
|
||||
for (j = 0; j < numpoints; j++)
|
||||
{
|
||||
VectorCopy(facepoints[j], cl_strisvertv[cl_numstrisvert]);
|
||||
cl_strisvertv[cl_numstrisvert][2] += 1;
|
||||
Vector4Set(cl_strisvertc[cl_numstrisvert], 0, 1, 0, 0.2);
|
||||
Vector2Set(cl_strisvertt[cl_numstrisvert], 0, 0);
|
||||
cl_numstrisvert++;
|
||||
}
|
||||
t->numidx = cl_numstrisidx - t->firstidx;
|
||||
t->numvert = cl_numstrisvert-t->firstvert;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return ((vec4_t*)enterplane - planes)+1;
|
||||
}
|
||||
}
|
||||
|
@ -3573,7 +3721,7 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
{
|
||||
vec3_t d[2];
|
||||
vec3_t p[4];
|
||||
vec4_t n[5];
|
||||
vec4_t n[6];
|
||||
int t;
|
||||
int i;
|
||||
|
||||
|
@ -3630,8 +3778,8 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//figure out where on the submodel the trace is.
|
||||
VectorSubtract (tr->start, s->ents[i]->ent.origin, start_l);
|
||||
VectorSubtract (tr->end, s->ents[i]->ent.origin, end_l);
|
||||
start_l[2] -= tr->mins[2];
|
||||
end_l[2] -= tr->mins[2];
|
||||
// start_l[2] -= tr->mins[2];
|
||||
// end_l[2] -= tr->mins[2];
|
||||
VectorScale(start_l, s->ents[i]->ent.scale, start_l);
|
||||
VectorScale(end_l, s->ents[i]->ent.scale, end_l);
|
||||
|
||||
|
@ -3649,6 +3797,26 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
etr.fraction = 1;
|
||||
model->funcs.NativeTrace (model, 0, frame, s->ents[i]->ent.axis, start_l, end_l, tr->mins, tr->maxs, tr->shape == iscapsule, tr->hitcontentsmask, &etr);
|
||||
|
||||
if (etr.startsolid)
|
||||
{ //many many bsp objects are not enclosed 'properly' (qbsp strips any surfaces outside the world).
|
||||
//this means that such bsps extend to infinity, resulting in sudden glitchy stuck issues when you enter a section containing such a bsp
|
||||
//so if we started solid, constrain that solidity to the volume of the submodel
|
||||
VectorCopy (s->ents[i]->ent.axis[0], n[0]);
|
||||
VectorNegate(s->ents[i]->ent.axis[0], n[1]);
|
||||
VectorCopy (s->ents[i]->ent.axis[1], n[2]);
|
||||
VectorNegate(s->ents[i]->ent.axis[1], n[3]);
|
||||
VectorCopy (s->ents[i]->ent.axis[2], n[4]);
|
||||
VectorNegate(s->ents[i]->ent.axis[2], n[5]);
|
||||
n[0][3] = DotProduct(n[0], s->ents[i]->ent.origin) + model->maxs[0];
|
||||
n[1][3] = DotProduct(n[1], s->ents[i]->ent.origin) + -model->mins[0];
|
||||
n[2][3] = DotProduct(n[2], s->ents[i]->ent.origin) + model->maxs[1];
|
||||
n[3][3] = DotProduct(n[3], s->ents[i]->ent.origin) + -model->mins[1];
|
||||
n[4][3] = DotProduct(n[4], s->ents[i]->ent.origin) + model->maxs[2];
|
||||
n[5][3] = DotProduct(n[5], s->ents[i]->ent.origin) + -model->mins[2];
|
||||
Heightmap_Trace_Brush(tr, n, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr->result->startsolid |= etr.startsolid;
|
||||
tr->result->allsolid |= etr.allsolid;
|
||||
if (etr.fraction < tr->frac)
|
||||
|
@ -3661,6 +3829,7 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
tr->plane[2] = etr.plane.normal[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
Sys_UnlockMutex(tr->hm->entitylock);
|
||||
}
|
||||
|
||||
|
@ -3697,17 +3866,15 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
VectorSet(p[2], tr->htilesize*(sx+0), tr->htilesize*(sy+1), s->heights[(tx+0)+(ty+1)*SECTHEIGHTSIZE]);
|
||||
VectorSet(p[3], tr->htilesize*(sx+1), tr->htilesize*(sy+1), s->heights[(tx+1)+(ty+1)*SECTHEIGHTSIZE]);
|
||||
|
||||
VectorSet(n[5], 0, 0, 1);
|
||||
#ifndef STRICTEDGES
|
||||
d1 = fabs(p[0][2] - p[3][2]);
|
||||
d2 = fabs(p[1][2] - p[2][2]);
|
||||
if (d1 < d2)
|
||||
{
|
||||
for (t = 0; t < 2; t++)
|
||||
{
|
||||
/*generate the brush (in world space*/
|
||||
if (t == 0)
|
||||
{
|
||||
VectorSubtract(p[3], p[2], d[0]);
|
||||
VectorSubtract(p[3], p[0], d[0]);
|
||||
VectorSubtract(p[2], p[0], d[1]);
|
||||
//left-most
|
||||
Vector4Set(n[0], -1, 0, 0, -tr->htilesize*(sx+0));
|
||||
|
@ -3725,10 +3892,14 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//down
|
||||
VectorNegate(n[3], n[4]);
|
||||
n[4][3] = DotProduct(n[4], p[0]) - n[4][2]*TERRAINTHICKNESS;
|
||||
|
||||
n[5][3] = max(p[0][2], p[2][2]);
|
||||
n[5][3] = max(n[5][3], p[3][2]);
|
||||
Heightmap_Trace_Brush(tr, n, 6);
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
VectorSubtract(p[1], p[0], d[0]);
|
||||
VectorSubtract(p[3], p[0], d[0]);
|
||||
VectorSubtract(p[3], p[1], d[1]);
|
||||
|
||||
//right-most
|
||||
|
@ -3747,17 +3918,16 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//down
|
||||
VectorNegate(n[3], n[4]);
|
||||
n[4][3] = DotProduct(n[4], p[0]) - n[4][2]*TERRAINTHICKNESS;
|
||||
}
|
||||
Heightmap_Trace_Brush(tr, n, 5);
|
||||
|
||||
n[5][3] = max(p[0][2], p[1][2]);
|
||||
n[5][3] = max(n[5][3], p[3][2]);
|
||||
Heightmap_Trace_Brush(tr, n, 6);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (t = 0; t < 2; t++)
|
||||
{
|
||||
/*generate the brush (in world space*/
|
||||
if (t == 0)
|
||||
{
|
||||
VectorSubtract(p[1], p[0], d[0]);
|
||||
VectorSubtract(p[2], p[0], d[1]);
|
||||
|
@ -3777,8 +3947,11 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//down
|
||||
VectorNegate(n[3], n[4]);
|
||||
n[4][3] = DotProduct(n[4], p[1]) - n[4][2]*TERRAINTHICKNESS;
|
||||
|
||||
n[5][3] = max(p[0][2], p[1][2]);
|
||||
n[5][3] = max(n[5][3], p[2][2]);
|
||||
Heightmap_Trace_Brush(tr, n, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract(p[3], p[2], d[0]);
|
||||
VectorSubtract(p[3], p[1], d[1]);
|
||||
|
@ -3799,8 +3972,10 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//down
|
||||
VectorNegate(n[3], n[4]);
|
||||
n[4][3] = DotProduct(n[4], p[1]) - n[4][2]*TERRAINTHICKNESS;
|
||||
}
|
||||
Heightmap_Trace_Brush(tr, n, 5);
|
||||
|
||||
n[5][3] = max(p[1][2], p[2][2]);
|
||||
n[5][3] = max(n[5][3], p[3][2]);
|
||||
Heightmap_Trace_Brush(tr, n, 6);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -3848,6 +4023,21 @@ qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec
|
|||
{
|
||||
hmtrace.shape = iscapsule;
|
||||
zbias = 0;
|
||||
|
||||
if (mataxis)
|
||||
VectorSet(hmtrace.up, mataxis[0][2], -mataxis[1][2], mataxis[2][2]);
|
||||
else
|
||||
VectorSet(hmtrace.up, 0, 0, 1);
|
||||
|
||||
//determine the capsule sizes
|
||||
hmtrace.capsulesize[0] = ((maxs[0]-mins[0]) + (maxs[1]-mins[1]))/4.0;
|
||||
hmtrace.capsulesize[1] = maxs[2];
|
||||
hmtrace.capsulesize[2] = mins[2];
|
||||
// zbias = (trace_capsulesize[1] > -hmtrace.capsulesize[2])?hmtrace.capsulesize[1]:-hmtrace.capsulesize[2];
|
||||
hmtrace.capsulesize[1] -= hmtrace.capsulesize[0];
|
||||
hmtrace.capsulesize[2] += hmtrace.capsulesize[0];
|
||||
|
||||
zbias = 0;
|
||||
}
|
||||
else if (mins[0] || mins[1] || mins[2] || maxs[0] || maxs[1] || maxs[2])
|
||||
{
|
||||
|
@ -4190,6 +4380,21 @@ static void ted_heightsmooth(void *ctx, hmsection_t *s, int idx, float wx, float
|
|||
else
|
||||
s->heights[idx] = s->heights[idx]*(1-w) + w**(float*)ctx;
|
||||
}
|
||||
static void ted_heightdebug(void *ctx, hmsection_t *s, int idx, float wx, float wy, float w)
|
||||
{
|
||||
int tx = idx/SECTHEIGHTSIZE, ty = idx % SECTHEIGHTSIZE;
|
||||
s->flags |= TSF_NOTIFY|TSF_DIRTY|TSF_EDITED|TSF_RELIGHT;
|
||||
/*interpolate the terrain towards a certain value*/
|
||||
|
||||
if (tx == 16)
|
||||
tx = 0;
|
||||
if (ty == 16)
|
||||
ty = 0;
|
||||
|
||||
// if (ty < tx)
|
||||
// tx = ty;
|
||||
s->heights[idx] = (tx>>1) * 32 + (ty>>1) * 32;
|
||||
}
|
||||
static void ted_heightraise(void *ctx, hmsection_t *s, int idx, float wx, float wy, float strength)
|
||||
{
|
||||
s->flags |= TSF_NOTIFY|TSF_DIRTY|TSF_EDITED|TSF_RELIGHT;
|
||||
|
@ -4583,7 +4788,62 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
{
|
||||
if (mod && mod->loadstate == MLS_LOADING)
|
||||
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
|
||||
if (mod && mod->loadstate == MLS_LOADED)
|
||||
}
|
||||
if (mod->loadstate != MLS_LOADED)
|
||||
return;
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case ter_ents_wipe:
|
||||
G_INT(OFS_RETURN) = PR_TempString(prinst, mod->entities);
|
||||
mod->entities = Z_Malloc(1);
|
||||
return;
|
||||
case ter_ents_concat:
|
||||
{
|
||||
char *olds = mod->entities;
|
||||
const char *news = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
size_t oldlen = strlen(olds);
|
||||
size_t newlen = strlen(news);
|
||||
mod->entities = Z_Malloc(oldlen + newlen + 1);
|
||||
memcpy(mod->entities, olds, oldlen);
|
||||
memcpy(mod->entities+oldlen, news, newlen);
|
||||
mod->entities[oldlen + newlen] = 0;
|
||||
Z_Free(olds);
|
||||
G_FLOAT(OFS_RETURN) = oldlen + newlen;
|
||||
}
|
||||
return;
|
||||
case ter_ents_get:
|
||||
G_INT(OFS_RETURN) = PR_TempString(prinst, mod->entities);
|
||||
return;
|
||||
case ter_save:
|
||||
if (mod->terrain)
|
||||
{
|
||||
quant = Heightmap_Save(mod->terrain);
|
||||
Con_DPrintf("ter_save: %g sections saved\n", quant);
|
||||
}
|
||||
G_FLOAT(OFS_RETURN) = quant;
|
||||
/*
|
||||
if (mod->type == mod_brush)
|
||||
{
|
||||
Con_Printf("that model isn't a suitable worldmodel\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_CreatePath(fname, FS_GAMEONLY);
|
||||
file = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
|
||||
if (!file)
|
||||
Con_Printf("unable to open %s\n", fname);
|
||||
else
|
||||
{
|
||||
Terr_WriteMapFile(file, mod);
|
||||
VFS_CLOSE(file);
|
||||
}
|
||||
}*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mod->terrain)
|
||||
{
|
||||
char basename[MAX_QPATH];
|
||||
COM_FileBase(mod->name, basename, sizeof(basename));
|
||||
|
@ -4593,9 +4853,6 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
return;
|
||||
Terr_FinishTerrain(mod);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
hm = mod->terrain;
|
||||
|
||||
pos[0] = G_FLOAT(OFS_PARM1+0) + hm->sectionsize * CHUNKBIAS;
|
||||
|
@ -4608,11 +4865,6 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
G_FLOAT(OFS_RETURN) = 1;
|
||||
Terr_PurgeTerrainModel(mod, false, true);
|
||||
break;
|
||||
case ter_save:
|
||||
quant = Heightmap_Save(hm);
|
||||
Con_DPrintf("ter_save: %g sections saved\n", quant);
|
||||
G_FLOAT(OFS_RETURN) = quant;
|
||||
break;
|
||||
case ter_sethole:
|
||||
/* {
|
||||
int x, y;
|
||||
|
@ -4643,6 +4895,8 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
if (IS_NAN(tally[0]))
|
||||
tally[0] = 0;
|
||||
ted_itterate(hm, tid_exponential, pos, radius, quant, SECTHEIGHTSIZE, ted_heightsmooth, &tally);
|
||||
|
||||
ted_itterate(hm, tid_exponential, pos, radius, quant, SECTHEIGHTSIZE, ted_heightdebug, &tally);
|
||||
break;
|
||||
case ter_height_smooth:
|
||||
tally[0] = 0;
|
||||
|
@ -6242,7 +6496,7 @@ void Mod_Terrain_Save_f(void)
|
|||
vfsfile_t *file;
|
||||
model_t *mod;
|
||||
const char *mapname = Cmd_Argv(1);
|
||||
const char *fname = Cmd_Argv(2);
|
||||
char fname[MAX_QPATH];
|
||||
if (Cmd_IsInsecure())
|
||||
{
|
||||
Con_Printf("Please use this command via the console\n");
|
||||
|
@ -6262,15 +6516,40 @@ void Mod_Terrain_Save_f(void)
|
|||
Con_Printf("no model loaded by that name\n");
|
||||
return;
|
||||
}
|
||||
if (!mod->terrain || mod->loadstate != MLS_LOADED)
|
||||
if (mod->loadstate != MLS_LOADED)
|
||||
{
|
||||
Con_Printf("that model has no content worth saving, or isn't fully loaded\n");
|
||||
Con_Printf("that model isn't fully loaded\n");
|
||||
return;
|
||||
}
|
||||
if (!*fname)
|
||||
fname = mod->name;
|
||||
if (*Cmd_Argv(2))
|
||||
Q_snprintfz(fname, sizeof(fname), "maps/%s.map", Cmd_Argv(2));
|
||||
else
|
||||
fname = va("maps/%s.map", fname);
|
||||
Q_snprintfz(fname, sizeof(fname), "%s", mod->name);
|
||||
|
||||
if (mod->type != mod_heightmap)
|
||||
{
|
||||
//warning: brushes are not saved unless its a .map
|
||||
COM_StripExtension(mod->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
|
||||
FS_CreatePath(fname, FS_GAMEONLY);
|
||||
file = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
|
||||
if (!file)
|
||||
Con_Printf("unable to open %s\n", fname);
|
||||
else
|
||||
{
|
||||
VFS_WRITE(file, mod->entities, strlen(mod->entities));
|
||||
VFS_CLOSE(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mod->type != mod_brush)
|
||||
{
|
||||
Con_Printf("that model isn't a suitable worldmodel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FS_CreatePath(fname, FS_GAMEONLY);
|
||||
file = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
|
||||
if (!file)
|
||||
|
@ -6281,6 +6560,8 @@ void Mod_Terrain_Save_f(void)
|
|||
VFS_CLOSE(file);
|
||||
}
|
||||
}
|
||||
FS_FlushFSHash();
|
||||
}
|
||||
qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||
{
|
||||
char token[8192];
|
||||
|
@ -6306,7 +6587,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
#endif
|
||||
|
||||
/*FIXME: we need to re-form the entities lump to insert model fields as appropriate*/
|
||||
mod->entities = out = ZG_Malloc(&mod->memgroup, buflen+1);
|
||||
mod->entities = out = Z_Malloc(buflen+1);
|
||||
|
||||
while(entities)
|
||||
{
|
||||
|
@ -6369,7 +6650,6 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
if (submod->loadstate == MLS_NOTLOADED)
|
||||
{
|
||||
submod->type = mod_heightmap;
|
||||
submod->entities = "";
|
||||
subhm = submod->terrain = Mod_LoadTerrainInfo(submod, submod->name, true);
|
||||
|
||||
subhm->exteriorcontents = FTECONTENTS_EMPTY;
|
||||
|
|
|
@ -520,6 +520,9 @@ void Mod_Purge(enum mod_purge_e ptype)
|
|||
mod->meshinfo = NULL;
|
||||
}
|
||||
|
||||
Z_Free(mod->entities);
|
||||
mod->entities = NULL;
|
||||
|
||||
//and obliterate anything else remaining in memory.
|
||||
ZG_FreeGroup(&mod->memgroup);
|
||||
mod->meshinfo = NULL;
|
||||
|
@ -2085,24 +2088,24 @@ void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
|||
Q_snprintfz(fname, sizeof(fname), "maps/%s/%s", mod_loadentfiles_dir.string, loadmodel->name+5);
|
||||
COM_StripExtension(fname, fname, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
loadmodel->entities = FS_LoadMallocGroupFile(&loadmodel->memgroup, fname, &sz);
|
||||
loadmodel->entities = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
}
|
||||
if (mod_loadentfiles.value && !loadmodel->entities)
|
||||
{
|
||||
COM_StripExtension(loadmodel->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
loadmodel->entities = FS_LoadMallocGroupFile(&loadmodel->memgroup, fname, &sz);
|
||||
loadmodel->entities = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
if (mod_loadentfiles.value && !loadmodel->entities)
|
||||
{ //tenebrae compat
|
||||
COM_StripExtension(loadmodel->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, ".edo", sizeof(fname));
|
||||
loadmodel->entities = FS_LoadMallocGroupFile(&loadmodel->memgroup, fname, &sz);
|
||||
loadmodel->entities = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
if (!loadmodel->entities)
|
||||
{
|
||||
loadmodel->entities = ZG_Malloc(&loadmodel->memgroup, l->filelen + 1);
|
||||
loadmodel->entities = Z_Malloc(l->filelen + 1);
|
||||
memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
|
||||
loadmodel->entities[l->filelen] = 0;
|
||||
}
|
||||
|
@ -4761,6 +4764,9 @@ TRACE(("LoadBrushModel %i\n", __LINE__));
|
|||
|
||||
submod->numclusters = bm->visleafs;
|
||||
|
||||
if (i)
|
||||
submod->entities = NULL;
|
||||
|
||||
memset(&submod->batches, 0, sizeof(submod->batches));
|
||||
submod->vbos = NULL;
|
||||
TRACE(("LoadBrushModel %i\n", __LINE__));
|
||||
|
|
|
@ -70,7 +70,7 @@ static void DL_OnError(void *c)
|
|||
#else
|
||||
dl->replycode = 404; //we don't actually know. should we not do this?
|
||||
#endif
|
||||
Con_Printf("download %p: error %i\n", dl, dl->replycode);
|
||||
Con_Printf("download: %s: error %i\n", dl->url, dl->replycode);
|
||||
dl->status = DL_FAILED;
|
||||
}
|
||||
static void DL_OnProgress(void *c, int position, int totalsize)
|
||||
|
|
|
@ -295,12 +295,85 @@ cl_expsprite 0
|
|||
//hide it in nq - WARNING: some mods use this sprite as a flame thrower.
|
||||
//r_effect "progs/s_explod.spr" hidden 1
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
//rogue te_explosion2 effect
|
||||
//note: if not otherwise defined, te_explosion2_BASE_RAND maps to this, and specifies the palette colours.
|
||||
r_part te_explosion2
|
||||
{
|
||||
type texturedspark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 65 31 95 256 8 32
|
||||
count 256
|
||||
scale 5
|
||||
scalefactor 1
|
||||
scaledelta -15
|
||||
alpha 0.2
|
||||
die 0.5
|
||||
blend add
|
||||
spawnmode ball
|
||||
spawnorg 1
|
||||
randomvel 1000
|
||||
friction 0.01
|
||||
gravity 100
|
||||
stretchfactor -80
|
||||
}
|
||||
//dragon fireball
|
||||
//r_part te_explosion2_228_5
|
||||
|
||||
//rogue multigrenade sub explosion
|
||||
//also triggered from a shielded rogue player touching another player (and doing some damage)
|
||||
//also used during the ending.
|
||||
//red particles
|
||||
//r_part te_explosion2_230_5
|
||||
|
||||
//rogue plasma explosion
|
||||
//also rogue timemachine explosion
|
||||
//white particles splaying outwards
|
||||
//r_part te_explosion2_244_3
|
||||
|
||||
//////////////////////////////////////////
|
||||
//for when a spawn dies.
|
||||
//also used by TF for emp explosions.
|
||||
//r_part te_tarexplosion
|
||||
//{
|
||||
//}
|
||||
r_part te_tarexplosion
|
||||
{
|
||||
type texturedspark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 65 31 95 256 8 32
|
||||
count 128
|
||||
scale 5
|
||||
scalefactor 1
|
||||
scaledelta -15
|
||||
rgb 0 0 17
|
||||
alpha 0.5
|
||||
die 0.5
|
||||
spawnmode ball
|
||||
spawnorg 1
|
||||
randomvel 500
|
||||
friction 0.01
|
||||
gravity 100
|
||||
stretchfactor -80
|
||||
}
|
||||
r_part +te_tarexplosion
|
||||
{
|
||||
type texturedspark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 65 31 95 256 8 32
|
||||
count 256
|
||||
scale 5
|
||||
scalefactor 1
|
||||
scaledelta -15
|
||||
rgb 83 67 115
|
||||
alpha 0.3
|
||||
die 0.5
|
||||
blend add
|
||||
spawnmode ball
|
||||
spawnorg 1
|
||||
randomvel 500
|
||||
friction 0.01
|
||||
gravity 100
|
||||
stretchfactor -80
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//cthon falling into lava.
|
||||
|
@ -444,6 +517,8 @@ r_part tr_vorespike
|
|||
//rygel's pack sucks
|
||||
r_trail "progs/v_spike.mdl" tr_vorespike
|
||||
|
||||
|
||||
////////////////////
|
||||
//enforcer laser effect
|
||||
r_part tr_enforcerlaser
|
||||
{
|
||||
|
@ -471,6 +546,79 @@ r_part tr_enforcerlaser
|
|||
}
|
||||
r_trail "progs/laser.mdl" tr_enforcerlaser
|
||||
|
||||
/////////////////////////////////////////
|
||||
//rogue wrath enemy's projectiles
|
||||
r_part tr_wrathball
|
||||
{
|
||||
type texturedspark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 97 95 191 256
|
||||
scale 15
|
||||
step 4
|
||||
alpha 0.3
|
||||
die 0.5
|
||||
rgb 255 0 0
|
||||
veladd -32
|
||||
spawnmode spiral
|
||||
spawnvel 16
|
||||
randomvel 32
|
||||
friction 0
|
||||
scalefactor 1
|
||||
blend add
|
||||
lighttime 0.2
|
||||
lightshadows 0
|
||||
lightradius 150
|
||||
lightrgb 1 0.27 0
|
||||
lightrgbfade 5 1 0
|
||||
lightcorona 2 0.5
|
||||
}
|
||||
r_trail "progs/w_ball.mdl" tr_wrathball
|
||||
|
||||
//wrath death
|
||||
//grey particles
|
||||
//no difference from the fallback except for the blend mode. this should ensure that we are not quite so invisible.
|
||||
r_part te_explosion2_0_4
|
||||
{
|
||||
type texturedspark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 65 31 95 256 8 32
|
||||
count 256
|
||||
scale 5
|
||||
scalefactor 1
|
||||
scaledelta -15
|
||||
alpha 0.2
|
||||
die 0.5
|
||||
spawnmode ball
|
||||
spawnorg 1
|
||||
randomvel 1000
|
||||
friction 0.01
|
||||
gravity 100
|
||||
stretchfactor -80
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
//rogue lavaspikes
|
||||
r_part tr_lavaspike
|
||||
{
|
||||
type spark
|
||||
texture "particles/fteparticlefont.tga"
|
||||
tcoords 1 97 95 191 256
|
||||
scale 15
|
||||
step 4
|
||||
alpha 0.3
|
||||
die 0.5
|
||||
rgb 255 0 0
|
||||
veladd -32
|
||||
spawnmode spiral
|
||||
spawnvel 16
|
||||
randomvel 32
|
||||
friction 0
|
||||
scalefactor 1
|
||||
blend add
|
||||
}
|
||||
r_trail "progs/lspike.mdl" tr_lavaspike
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
//scrag missiles.
|
||||
r_part tr_wizspike
|
||||
|
|
|
@ -794,9 +794,32 @@ void NPP_NQFlush(void)
|
|||
buffer[0] = svcfte_cgamepacket;
|
||||
}
|
||||
break;
|
||||
case TE_EXPLOSION:
|
||||
if (writedest == &sv.datagram)
|
||||
{ //for old clients, use a te_explosion.
|
||||
//for clients that support it, use a TEQW_EXPLOSIONNOSPRITE
|
||||
vec3_t org;
|
||||
coorddata cd;
|
||||
if (sv.multicast.cursize + bufferlen > sv.multicast.maxsize)
|
||||
SV_FlushBroadcasts();
|
||||
SZ_Write(&sv.multicast, buffer, bufferlen);
|
||||
|
||||
memcpy(&cd, &buffer[2+destprim->coordsize*0], destprim->coordsize);
|
||||
org[0] = MSG_FromCoord(cd, destprim->coordsize);
|
||||
memcpy(&cd, &buffer[2+destprim->coordsize*1], destprim->coordsize);
|
||||
org[1] = MSG_FromCoord(cd, destprim->coordsize);
|
||||
memcpy(&cd, &buffer[2+destprim->coordsize*2], destprim->coordsize);
|
||||
org[2] = MSG_FromCoord(cd, destprim->coordsize);
|
||||
|
||||
requireextension = PEXT_TE_BULLET;
|
||||
SV_MulticastProtExt(org, multicasttype, pr_global_struct->dimension_send, 0, requireextension);
|
||||
buffer[1] = TEQW_EXPLOSIONNOSPRITE;
|
||||
}
|
||||
break;
|
||||
case TENQ_EXPLOSION2: //happens with rogue.
|
||||
bufferlen -= 2; //trim the colour
|
||||
buffer[1] = TE_EXPLOSION;
|
||||
//bufferlen -= 2; //trim the colour
|
||||
//buffer[1] = TE_EXPLOSION;
|
||||
buffer[1] = TEQW_EXPLOSION2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1119,7 +1142,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
|
|||
case TE_SPIKE:
|
||||
case TE_SUPERSPIKE:
|
||||
multicastpos=2;
|
||||
multicasttype=MULTICAST_PHS_R;
|
||||
multicasttype=MULTICAST_PHS;
|
||||
protocollen = destprim->coordsize*3+sizeof(qbyte)*2;
|
||||
break;
|
||||
case TE_LAVASPLASH:
|
||||
|
@ -1143,7 +1166,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
|
|||
data = TEQW_EXPLOSION2;
|
||||
protocollen = sizeof(qbyte)*4 + destprim->coordsize*3;
|
||||
multicastpos=2;
|
||||
multicasttype=MULTICAST_PHS_R;
|
||||
multicasttype=MULTICAST_PHS;
|
||||
break;
|
||||
case TE_EXPLOSIONSMALL2:
|
||||
data = TE_EXPLOSION;
|
||||
|
|
|
@ -4998,6 +4998,14 @@ void SV_point_tempentity (vec3_t o, int type, int count) //count (usually 1) is
|
|||
MSG_WriteByte (&sv.nqmulticast, type); //nq doesn't have a count.
|
||||
#endif
|
||||
break;
|
||||
case TEQW_EXPLOSIONNOSPRITE:
|
||||
MSG_WriteByte (&sv.multicast, TE_EXPLOSION);
|
||||
#ifdef NQPROT
|
||||
MSG_WriteByte (&sv.nqmulticast, TE_EXPLOSION);
|
||||
#endif
|
||||
type = TEQW_EXPLOSIONNOSPRITE;
|
||||
split = PEXT_TE_BULLET;
|
||||
break;
|
||||
case TE_LIGHTNING1:
|
||||
case TE_LIGHTNING2:
|
||||
case TE_LIGHTNING3:
|
||||
|
@ -7964,6 +7972,9 @@ static void QCBUILTIN PF_te_superspikequad(pubprogfuncs_t *prinst, struct global
|
|||
//void(vector org) te_explosion = #421;
|
||||
static void QCBUILTIN PF_te_explosion(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
if (progstype != PROG_QW)
|
||||
SV_point_tempentity(G_VECTOR(OFS_PARM0), TEQW_EXPLOSIONNOSPRITE, 1);
|
||||
else
|
||||
SV_point_tempentity(G_VECTOR(OFS_PARM0), TE_EXPLOSION, 1);
|
||||
}
|
||||
//DP_TE_QUADEFFECTS1
|
||||
|
@ -8008,11 +8019,32 @@ static void QCBUILTIN PF_te_teleport(pubprogfuncs_t *prinst, struct globalvars_s
|
|||
}
|
||||
|
||||
//DP_TE_STANDARDEFFECTBUILTINS
|
||||
//void(vector org, float color) te_explosion2 = #427;
|
||||
//void(vector org, float color, float length) te_explosion2 = #427;
|
||||
static void QCBUILTIN PF_te_explosion2(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
//FIXME: QW doesn't support TE_EXPLOSION2...
|
||||
SV_point_tempentity(G_VECTOR(OFS_PARM0), TE_EXPLOSION, 1);
|
||||
float *org = G_VECTOR(OFS_PARM0);
|
||||
int start = G_FLOAT(OFS_PARM1);
|
||||
int length = G_FLOAT(OFS_PARM2);
|
||||
start = bound(0, start, 255);
|
||||
length = bound(0, length, 255-start);
|
||||
|
||||
MSG_WriteByte (&sv.multicast, svc_temp_entity);
|
||||
MSG_WriteByte (&sv.multicast, TEQW_EXPLOSION2);
|
||||
MSG_WriteCoord (&sv.multicast, org[0]);
|
||||
MSG_WriteCoord (&sv.multicast, org[1]);
|
||||
MSG_WriteCoord (&sv.multicast, org[2]);
|
||||
MSG_WriteByte (&sv.multicast, start);
|
||||
MSG_WriteByte (&sv.multicast, length);
|
||||
#ifdef NQPROT
|
||||
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
|
||||
MSG_WriteByte (&sv.nqmulticast, TENQ_EXPLOSION2);
|
||||
MSG_WriteCoord (&sv.nqmulticast, org[0]);
|
||||
MSG_WriteCoord (&sv.nqmulticast, org[1]);
|
||||
MSG_WriteCoord (&sv.nqmulticast, org[2]);
|
||||
MSG_WriteByte (&sv.nqmulticast, start);
|
||||
MSG_WriteByte (&sv.nqmulticast, length);
|
||||
#endif
|
||||
SV_MulticastProtExt(org, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0);
|
||||
}
|
||||
|
||||
//DP_TE_STANDARDEFFECTBUILTINS
|
||||
|
@ -8784,7 +8816,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
|
|||
pmove.groundent = 0;
|
||||
pmove.waterlevel = 0;
|
||||
pmove.watertype = 0;
|
||||
pmove.capsule = (ent->xv->geomtype == GEOMTYPE_CYLINDER);
|
||||
pmove.capsule = (ent->xv->geomtype == GEOMTYPE_CAPSULE);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
|
@ -11152,6 +11184,9 @@ void PR_DumpPlatform_f(void)
|
|||
{"TEREDIT_TINT", "const float", CS, NULL, ter_tint},
|
||||
{"TEREDIT_RESET_SECT", "const float", CS, NULL, ter_reset},
|
||||
{"TEREDIT_RELOAD_SECT", "const float", CS, NULL, ter_reloadsect},
|
||||
{"TEREDIT_ENTS_WIPE", "const float", CS, NULL, ter_ents_wipe},
|
||||
{"TEREDIT_ENTS_CONCAT", "const float", CS, NULL, ter_ents_concat},
|
||||
{"TEREDIT_ENTS_GET", "const float", CS, NULL, ter_ents_get},
|
||||
|
||||
{"SLIST_HOSTCACHEVIEWCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHEVIEWCOUNT},
|
||||
{"SLIST_HOSTCACHETOTALCOUNT", "const float", CS|MENU, NULL, SLIST_HOSTCACHETOTALCOUNT},
|
||||
|
|
|
@ -265,6 +265,19 @@ and the extension fields are added on the end and can have extra vm-specific stu
|
|||
comfieldfloat(uniquespawnid,"Incremented by 1 whenever the entity is respawned. Persists across remove calls, for when the two-second grace period is insufficient.")/*FTE_ENT_UNIQUESPAWNID*/\
|
||||
comfieldfunction(customizeentityforclient, ".float()","Called just before an entity is sent to a client (non-csqc protocol). This gives you a chance to tailor 'self' according to what 'other' should see.")
|
||||
|
||||
#ifdef HALFLIFEMODELS
|
||||
#define HALFLIFEMODEL_FIELDS \
|
||||
comfieldfloat(bonecontrol1,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol2,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol3,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol4,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol5,"Halflife model format bone controller. This typically affects the mouth.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(subblendfrac,"Weird animation value specific to halflife models. On player models, this typically affects the spine's pitch.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(basesubblendfrac,"See basebone") /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/
|
||||
#else
|
||||
#define HALFLIFEMODEL_FIELDS
|
||||
#endif
|
||||
|
||||
//this is the list for all the csqc fields.
|
||||
//(the #define is so the list always matches the ones pulled out)
|
||||
#define csqcextfields \
|
||||
|
@ -286,15 +299,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
|
|||
comfieldfloat(baseframe2time,"See basebone") /*FTE_CSQC_BASEFRAME*/\
|
||||
comfieldfloat(baselerpfrac,"See basebone") /*FTE_CSQC_BASEFRAME*/\
|
||||
comfieldfloat(basebone,"The base* frame animations are equivelent to their non-base versions, except that they only affect bone numbers below the 'basebone' value. This means that the base* animation can affect the legs of a skeletal model independantly of the normal animation fields affecting the torso area. For more complex animation than this, use skeletal objects.") /*FTE_CSQC_BASEFRAME*/\
|
||||
\
|
||||
comfieldfloat(bonecontrol1,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol2,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol3,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol4,"Halflife model format bone controller. On player models, this typically affects the spine's yaw.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(bonecontrol5,"Halflife model format bone controller. This typically affects the mouth.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(subblendfrac,"Weird animation value specific to halflife models. On player models, this typically affects the spine's pitch.") /*FTE_CSQC_HALFLIFE_MODELS*/\
|
||||
comfieldfloat(basesubblendfrac,"See basebone") /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/\
|
||||
\
|
||||
HALFLIFEMODEL_FIELDS \
|
||||
comfieldfloat(drawmask, "Matces the bitmask passed to the addentities builtin, to easily submit entities to the renderer. Not otherwise meaningful.") /*So that the qc can specify all rockets at once or all bannanas at once*/ \
|
||||
comfieldfunction(predraw, ".float()","Called as part of the addentities builtin. Returns one of the PREDRAW_ constants. This gives you a chance to interpolate or animate entities as desired.") /*If present, is called just before it's drawn.*/
|
||||
|
||||
|
|
|
@ -397,6 +397,7 @@ void SV_Map_f (void)
|
|||
char spot[MAX_QPATH];
|
||||
char expanded[MAX_QPATH];
|
||||
char *nextserver;
|
||||
qboolean preserveplayers= false;
|
||||
qboolean isrestart = false; //don't hurt settings
|
||||
qboolean newunit = false; //no hubcache
|
||||
qboolean flushparms = false; //flush parms+serverflags
|
||||
|
@ -407,6 +408,7 @@ void SV_Map_f (void)
|
|||
qboolean waschangelevel = false;
|
||||
int i;
|
||||
char *startspot;
|
||||
float oldtime;
|
||||
|
||||
nextserver = 0;
|
||||
|
||||
|
@ -486,10 +488,18 @@ void SV_Map_f (void)
|
|||
Q_strncpyz(level, "start", sizeof(level));
|
||||
}
|
||||
|
||||
//override the startspot
|
||||
if (startspot && !strcmp(startspot, "."))
|
||||
{
|
||||
preserveplayers = true;
|
||||
startspot = NULL;
|
||||
}
|
||||
if (!startspot)
|
||||
{
|
||||
//revert the startspot if its not overridden
|
||||
Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot));
|
||||
startspot = spot;
|
||||
}
|
||||
}
|
||||
|
||||
// check to make sure the level exists
|
||||
if (*level == '*')
|
||||
|
@ -614,11 +624,32 @@ void SV_Map_f (void)
|
|||
MP_Toggle(0);
|
||||
#endif
|
||||
|
||||
oldtime = sv.time;
|
||||
if (preserveplayers && svprogfuncs)
|
||||
{
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++) //we need to drop all q2 clients. We don't mix q1w with q2.
|
||||
{
|
||||
char buffer[8192], *buf;
|
||||
size_t bufsize = 0;
|
||||
if (svs.clients[i].state>cs_connected)
|
||||
{
|
||||
buf = svprogfuncs->saveent(svprogfuncs, buffer, &bufsize, sizeof(buffer), svs.clients[i].edict);
|
||||
if (svs.clients[i].spawninfo)
|
||||
Z_Free(svs.clients[i].spawninfo);
|
||||
svs.clients[i].spawninfo = Z_Malloc(bufsize+1);
|
||||
memcpy(svs.clients[i].spawninfo, buf, bufsize+1);
|
||||
svs.clients[i].spawninfotime = sv.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++) //we need to drop all q2 clients. We don't mix q1w with q2.
|
||||
{
|
||||
if (svs.clients[i].state>cs_connected) //so that we don't send a datagram
|
||||
svs.clients[i].state=cs_connected;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
S_StopAllSounds (true);
|
||||
|
@ -626,6 +657,8 @@ void SV_Map_f (void)
|
|||
SCR_ImageName(level);
|
||||
#endif
|
||||
|
||||
// if (!preserveplayers)
|
||||
{
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
/*pass the new map's name as an extension, so appropriate loading screens can be shown*/
|
||||
|
@ -651,6 +684,7 @@ void SV_Map_f (void)
|
|||
|
||||
if (flushparms)
|
||||
svs.serverflags = 0;
|
||||
}
|
||||
|
||||
SCR_SetLoadingFile("spawnserver");
|
||||
if (newunit || !startspot || cinematic || !SV_LoadLevelCache(NULL, level, startspot, false))
|
||||
|
@ -680,6 +714,14 @@ void SV_Map_f (void)
|
|||
SV_GetNewSpawnParms(host_client);
|
||||
}
|
||||
|
||||
if (preserveplayers && svprogfuncs && host_client->state == cs_spawned && host_client->spawninfo)
|
||||
{
|
||||
int j = 0;
|
||||
svprogfuncs->restoreent(svprogfuncs, host_client->spawninfo, &j, host_client->edict);
|
||||
host_client->istobeloaded = true;
|
||||
host_client->state=cs_connected;
|
||||
}
|
||||
|
||||
if (host_client->controller)
|
||||
continue;
|
||||
if (host_client->state>=cs_connected)
|
||||
|
|
|
@ -923,7 +923,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
Q_strncpyz(cl.serverinfo, svs.info, sizeof(cl.serverinfo));
|
||||
if (!isDedicated)
|
||||
CL_CheckServerInfo();
|
||||
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1329,7 +1329,12 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
|
|||
// move origin
|
||||
VectorScale (ent->v->velocity, host_frametime, move);
|
||||
if (!DotProduct(move, move))
|
||||
{
|
||||
//rogue buzzsaws are vile and jerkily move via setorigin, and need to be relinked so that they can touch path corners.
|
||||
if (ent->v->solid && ent->v->nextthink)
|
||||
World_LinkEdict (w, ent, true);
|
||||
return;
|
||||
}
|
||||
|
||||
fl = 0;
|
||||
#ifndef CLIENTONLY
|
||||
|
@ -1340,7 +1345,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
|
|||
|
||||
trace = WPhys_PushEntity (w, ent, move, fl);
|
||||
|
||||
if (trace.allsolid)
|
||||
if (trace.allsolid && ent->v->solid != SOLID_NOT && ent->v->solid != SOLID_TRIGGER)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
if (progstype != PROG_H2)
|
||||
|
|
|
@ -6397,7 +6397,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
//
|
||||
// angles
|
||||
// show 1/3 the pitch angle and all the roll angle
|
||||
if (sv_player->v->health > 0)
|
||||
if (sv_player->v->health > 0 && sv_player->v->movetype)
|
||||
{
|
||||
if (sv_player->v->movetype == MOVETYPE_6DOF)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ void emscriptenfte_al_loadaudiofile(int al_buf, void *data, int datasize);
|
|||
//avoid all of emscripten's sdl emulation.
|
||||
//this resolves input etc issues.
|
||||
unsigned long emscriptenfte_ticks_ms(void);
|
||||
void emscriptenfte_updatepointerlock(int wantpointerlock, int hidecursor);
|
||||
void emscriptenfte_polljoyevents(void);
|
||||
void emscriptenfte_settitle(const char *text);
|
||||
int emscriptenfte_setupcanvas(
|
||||
|
|
|
@ -59,6 +59,8 @@ mergeInto(LibraryManager.library,
|
|||
$FTEC:
|
||||
{
|
||||
ctxwarned:0,
|
||||
pointerislocked:0,
|
||||
pointerwantlock:0,
|
||||
linebuffer:'',
|
||||
w: -1,
|
||||
h: -1,
|
||||
|
@ -128,13 +130,21 @@ mergeInto(LibraryManager.library,
|
|||
break;
|
||||
case 'mousedown':
|
||||
window.focus();
|
||||
//older browsers need fullscreen in order for requestPointerLock to work.
|
||||
//newer browsers can still break pointer locks when alt-tabbing, even without breaking fullscreen.
|
||||
//so lets spam requests for it
|
||||
if (Browser.isFullScreen == 0)
|
||||
if (FTEC.evcb.wantfullscreen != 0)
|
||||
if (Runtime.dynCall('i', FTEC.evcb.wantfullscreen, []))
|
||||
{
|
||||
Browser.requestFullScreen(true, true);
|
||||
}
|
||||
if (FTEC.pointerwantlock != 0 && FTEC.pointerislocked == 0)
|
||||
{
|
||||
FTEC.pointerislocked = -1; //don't repeat the request on every click. firefox has a fit at that, so require the mouse to leave the element or something before we retry.
|
||||
Module['canvas'].requestPointerLock();
|
||||
}
|
||||
//fallthrough
|
||||
case 'mouseup':
|
||||
if (FTEC.evcb.button != 0)
|
||||
{
|
||||
|
@ -156,6 +166,16 @@ mergeInto(LibraryManager.library,
|
|||
for (var i = 0; i < 8; i++)
|
||||
Runtime.dynCall('viii', FTEC.evcb.button, [0, false, i]);
|
||||
}
|
||||
if (FTEC.pointerislocked == -1)
|
||||
FTEC.pointerislocked = 0;
|
||||
break;
|
||||
case 'focus':
|
||||
case 'blur':
|
||||
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 16, 0]); //shift
|
||||
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 17, 0]); //alt
|
||||
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 18, 0]); //ctrl
|
||||
if (FTEC.pointerislocked == -1)
|
||||
FTEC.pointerislocked = 0;
|
||||
break;
|
||||
case 'keypress':
|
||||
if (FTEC.evcb.key != 0)
|
||||
|
@ -237,13 +257,39 @@ mergeInto(LibraryManager.library,
|
|||
Runtime.dynCall('viid', FTEC.evcb.jbutton, [gp.index, j, 0]);
|
||||
console.log("Gamepad disconnected from index %d: %s", gp.index, gp.id);
|
||||
break;
|
||||
case 'pointerlockchange':
|
||||
case 'mozpointerlockchange':
|
||||
case 'webkitpointerlockchange':
|
||||
FTEC.pointerislocked = document.pointerLockElement === Module['canvas'] ||
|
||||
document.mozPointerLockElement === Module['canvas'] ||
|
||||
document.webkitPointerLockElement === Module['canvas'];
|
||||
console.log("Pointer lock now " + FTEC.pointerislocked);
|
||||
break;
|
||||
default:
|
||||
console.log(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
emscriptenfte_polljoyevents : function(be,ae)
|
||||
emscriptenfte_updatepointerlock : function(wantlock, softcursor)
|
||||
{
|
||||
FTEC.pointerwantlock = wantlock;
|
||||
//we can only apply locks when we're clicked, but should be able to unlock any time.
|
||||
if (wantlock == 0 && FTEC.pointerislocked != 0)
|
||||
{
|
||||
document.exitPointerLock = document.exitPointerLock ||
|
||||
document.mozExitPointerLock ||
|
||||
document.webkitExitPointerLock;
|
||||
FTEC.pointerislocked = 0;
|
||||
if (document.exitPointerLock)
|
||||
document.exitPointerLock();
|
||||
}
|
||||
if (softcursor)
|
||||
Module.canvas.style.cursor = "none"; //hide the cursor, we'll do a soft-cursor when one is needed.
|
||||
else
|
||||
Module.canvas.style.cursor = "default"; //restore the cursor
|
||||
},
|
||||
emscriptenfte_polljoyevents : function()
|
||||
{
|
||||
//with events, we can do unplug stuff properly.
|
||||
//otherwise hot unplug might be buggy.
|
||||
|
@ -301,13 +347,21 @@ mergeInto(LibraryManager.library,
|
|||
if (!FTEC.donecb)
|
||||
{
|
||||
FTEC.donecb = 1;
|
||||
var events = ['mousedown', 'mouseup', 'mousemove', 'wheel', 'mousewheel', 'mouseout', 'keypress', 'keydown', 'keyup', 'touchstart', 'touchend', 'touchcancel', 'touchleave', 'touchmove', 'dragenter', 'dragover', 'drop', 'gamepadconnected', 'gamepaddisconnected', 'message'];
|
||||
var events = ['mousedown', 'mouseup', 'mousemove', 'wheel', 'mousewheel', 'mouseout',
|
||||
'keypress', 'keydown', 'keyup',
|
||||
'touchstart', 'touchend', 'touchcancel', 'touchleave', 'touchmove',
|
||||
'dragenter', 'dragover', 'drop',
|
||||
'gamepadconnected', 'gamepaddisconnected',
|
||||
'message',
|
||||
'pointerlockchange', 'mozpointerlockchange', 'webkitpointerlockchange',
|
||||
'focus', 'blur']; //try to fix alt-tab
|
||||
events.forEach(function(event)
|
||||
{
|
||||
Module['canvas'].addEventListener(event, FTEC.handleevent, true);
|
||||
});
|
||||
|
||||
var docevents = ['keypress', 'keydown', 'keyup'];
|
||||
var docevents = ['keypress', 'keydown', 'keyup',
|
||||
'pointerlockchange', 'mozpointerlockchange', 'webkitpointerlockchange'];
|
||||
docevents.forEach(function(event)
|
||||
{
|
||||
document.addEventListener(event, FTEC.handleevent, true);
|
||||
|
@ -354,11 +408,6 @@ mergeInto(LibraryManager.library,
|
|||
};
|
||||
window.onresize();
|
||||
|
||||
if (evmouse)
|
||||
Module.canvas.style.cursor = "none"; //hide the cursor, we'll do a soft-cursor when one is needed.
|
||||
else
|
||||
Module.canvas.style.cursor = "default"; //restore the cursor
|
||||
|
||||
if (FTEC.evcb.hashchange)
|
||||
{
|
||||
window.onhashchange = function()
|
||||
|
@ -367,6 +416,8 @@ mergeInto(LibraryManager.library,
|
|||
};
|
||||
}
|
||||
|
||||
_emscriptenfte_updatepointerlock(false, false);
|
||||
|
||||
return 1;
|
||||
},
|
||||
emscriptenfte_settitle : function(txt)
|
||||
|
|
|
@ -193,8 +193,12 @@ void DOM_LoadFile(char *loc, char *mime, int handle)
|
|||
}
|
||||
int VID_ShouldSwitchToFullscreen(void)
|
||||
{ //if false, mouse grabs won't work and we'll be forced to touchscreen mode.
|
||||
//we can only go fullscreen when the user clicks something.
|
||||
//this means that the user will get pissed off at the fullscreen state changing when they first click on the menus after it loading up.
|
||||
//this is confounded by escape bringing up the menu. <ESC>GRR IT CHANGED MODE!<options>WTF IT CHANGED AGAIN FUCKING PIECE OF SHIT!.
|
||||
//annoying, but that's web browsers for you. the best thing we can do is to not regrab until they next click while actually back in the game.
|
||||
extern cvar_t vid_fullscreen;
|
||||
return !!vid_fullscreen.value;
|
||||
return !!vid_fullscreen.value && (!Key_Dest_Has(kdm_console | kdm_cwindows | kdm_emenu) || !Key_MouseShouldBeFree());
|
||||
}
|
||||
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
|
||||
{
|
||||
|
@ -280,6 +284,8 @@ void GLVID_SetCaption(char *text)
|
|||
void Sys_SendKeyEvents(void)
|
||||
{
|
||||
/*most callbacks happen outside our code, we don't need to poll for events - except for joysticks*/
|
||||
qboolean shouldbefree = Key_MouseShouldBeFree();
|
||||
emscriptenfte_updatepointerlock(_windowed_mouse.ival && !shouldbefree, shouldbefree);
|
||||
emscriptenfte_polljoyevents();
|
||||
}
|
||||
/*various stuff for joysticks, which we don't support in this port*/
|
||||
|
|
Loading…
Reference in a new issue