diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 507675df0..fbc6b15f7 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -145,10 +145,20 @@ typedef enum { CG_CEIL, CG_TESTPRINTINT, CG_TESTPRINTFLOAT, - CG_ACOS + CG_ACOS, + + CG_FTE_FINDPARTICLEEFFECT = 200, + CG_FTE_SPAWNPARTICLEEFFECT, + CG_FTE_SPAWNPARTICLETRAIL, + CG_FTE_FREEPARTICLESTATE } cgameImport_t; - +/* +int CG_FTE_FINDPARTICLEEFFECT(char *particleeffectname) = #200; +int CG_FTE_SPAWNPARTICLEEFFECT(vec3_t pos, vec3_t dir, float count, int effectnum, void *pstate) = #201; +int CG_FTE_SPAWNPARTICLETRAIL(vec3_t start, vec3_t end, int effectnum, void *pstate) = #202; +void CG_FTE_FREEPARTICLESTATE(void *pstate) = #203; +*/ /* ================================================================== @@ -1019,6 +1029,16 @@ vec3_t listener_up; VALIDATEPOINTER(arg[2], sizeof(fontInfo_t)); UI_RegisterFont(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_POINTER(arg[2])); break; + + case CG_FTE_FINDPARTICLEEFFECT: + return P_FindParticleType(VM_POINTER(arg[0])); + case CG_FTE_SPAWNPARTICLEEFFECT: + return P_RunParticleEffectState(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_FLOAT(arg[2]), VM_LONG(arg[3]), VM_POINTER(arg[4])); + case CG_FTE_SPAWNPARTICLETRAIL: + return P_ParticleTrail(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), VM_POINTER(arg[3])); + case CG_FTE_FREEPARTICLESTATE: + P_DelinkTrailstate(VM_POINTER(arg[0])); + break; default: Con_Printf("Q3CG: Bad system trap: %d\n", fn); } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index e28895fc6..be72d2f66 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1191,6 +1191,7 @@ void CL_Disconnect (void) cls.protocol = CP_UNKNOWN; cl.servercount = 0; cls.findtrack = false; + cls.realserverip.type = NA_INVALID; Validation_DelatchRulesets(); @@ -1740,9 +1741,9 @@ void CL_Packet_f (void) adr.address.ip[3] = cls.netchan.remote_address.address.ip[3]; adr.port = cls.netchan.remote_address.port; Con_Printf (CON_WARNING "Server is broken. Trying to send to server instead.\n"); - } + cls.realserverip = adr; Con_DPrintf ("Sending realip packet\n"); } else if (!ruleset_allow_packet.value) @@ -2000,6 +2001,12 @@ void CL_ConnectionlessPacket (void) char data[256]; int len; + if (cls.realserverip.type == NA_INVALID) + return; //not done a realip yet + + if (NET_CompareBaseAdr(cls.realserverip, net_from) == false) + return; //only reply if it came from the real server's ip. + data[0] = 0xff; data[1] = 0xff; data[2] = 0xff; @@ -2007,21 +2014,12 @@ void CL_ConnectionlessPacket (void) data[4] = A2A_ACK; data[5] = 0; - if (!cls.state || !NET_CompareAdr(cls.netchan.remote_address, net_from)) - { - Con_TPrintf (TL_ST_COLON, NET_AdrToString (net_from)); - Con_TPrintf (TLC_A2A_PING); - len = 6; - } - else - { - //ack needs two parameters to work with realip properly. - //firstly it needs an auth message, so it can't be spoofed. - //secondly, it needs a copy of the realip ident, so you can't report a different player's client (you would need access to their ip). - data[5] = ' '; - sprintf(data+6, "%i %i", atoi(MSG_ReadString()), cls.realip_ident); - len = strlen(data); - } + //ack needs two parameters to work with realip properly. + //firstly it needs an auth message, so it can't be spoofed. + //secondly, it needs a copy of the realip ident, so you can't report a different player's client (you would need access to their ip). + data[5] = ' '; + sprintf(data+6, "%i %i", atoi(MSG_ReadString()), cls.realip_ident); + len = strlen(data); NET_SendPacket (NS_CLIENT, len, &data, net_from); return; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 86bde2e72..45d1e696a 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -733,6 +733,9 @@ int CL_LoadModels(int stage) if (!cl.worldmodel || cl.worldmodel->type == mod_dummy) Host_EndGame("Worldmodel wasn't sent\n"); + if (cl.worldmodel->fromgame == fg_quake) + cl.hexen2pickups = cl.worldmodel->hulls[MAX_MAP_HULLSDH2-1].available; + R_CheckSky(); CSQC_WorldLoaded(); @@ -2999,25 +3002,25 @@ void CL_NewTranslation (int slot) local = cl.playernum[0]; if (cl.teamplay && !strcmp(player->team, cl.players[local].team)) { - if (cl_teamtopcolor>=0) + if (cl_teamtopcolor != ~0) top = cl_teamtopcolor; - if (cl_teambottomcolor>=0) + if (cl_teambottomcolor != ~0) bottom = cl_teambottomcolor; } else { - if (cl_enemytopcolor>=0) + if (cl_enemytopcolor != ~0) top = cl_enemytopcolor; - if (cl_enemybottomcolor>=0) + if (cl_enemybottomcolor != ~0) bottom = cl_enemybottomcolor; } } - +/* if (top > 13 || top < 0) top = 13; if (bottom > 13 || bottom < 0) bottom = 13; - +*/ #ifdef SWQUAKE if (qrenderer == QR_SOFTWARE) { @@ -3043,15 +3046,32 @@ CL_UpdateUserinfo */ void CL_ProcessUserInfo (int slot, player_info_t *player) { + char *col; Q_strncpyz (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name)); Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team)); - player->rtopcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor")); - player->rbottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor")); + + col = Info_ValueForKey (player->userinfo, "topcolor"); + if (!strncmp(col, "0x", 2)) + player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16); + else + player->rtopcolor = atoi(col); + + col = Info_ValueForKey (player->userinfo, "bottomcolor"); + if (!strncmp(col, "0x", 2)) + player->rbottomcolor = 0xff000000|strtoul(col+2, NULL, 16); + else + player->rbottomcolor = atoi(col); + if (atoi(Info_ValueForKey (player->userinfo, "*spectator"))) player->spectator = true; else player->spectator = false; - +/* + if (player->rtopcolor > 13) + player->rtopcolor = 13; + if (player->rbottomcolor > 13) + player->rbottomcolor = 13; +*/ player->model = NULL; // If it's us diff --git a/engine/client/client.h b/engine/client/client.h index 4a9e8e762..2698d15af 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -144,11 +144,11 @@ typedef struct player_info_s qboolean ignored; // skin information - int rtopcolor; //real, according to their userinfo - int rbottomcolor; + unsigned int rtopcolor; //real, according to their userinfo + unsigned int rbottomcolor; - int ttopcolor; //team, according to colour forcing - int tbottomcolor; + unsigned int ttopcolor; //team, according to colour forcing + unsigned int tbottomcolor; #ifdef SWQUAKE struct palremap_s *palremap; @@ -308,6 +308,7 @@ typedef struct int framecount; int realip_ident; + netadr_t realserverip; // network stuff netchan_t netchan; @@ -580,6 +581,7 @@ typedef struct int deathmatch; qboolean teamfortress; //*sigh*. This is used for teamplay stuff. This sucks. + qboolean hexen2pickups; qboolean sendprespawn; int contentstage; @@ -592,10 +594,10 @@ typedef struct } ktprostate; } client_state_t; -extern int cl_teamtopcolor; -extern int cl_teambottomcolor; -extern int cl_enemytopcolor; -extern int cl_enemybottomcolor; +extern unsigned int cl_teamtopcolor; +extern unsigned int cl_teambottomcolor; +extern unsigned int cl_enemytopcolor; +extern unsigned int cl_enemybottomcolor; //FPD values //(commented out ones are ones that we don't support) diff --git a/engine/client/merged.h b/engine/client/merged.h index 4d9708a31..98547188a 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -20,6 +20,7 @@ extern mpic_t *(*Draw_SafeCachePic) (char *path); extern void (*Draw_Init) (void); extern void (*Draw_ReInit) (void); extern void (*Draw_Character) (int x, int y, unsigned int num); +extern void (*Draw_TinyCharacter) (int x, int y, unsigned int num); extern void (*Draw_ColouredCharacter) (int x, int y, unsigned int num); extern void (*Draw_String) (int x, int y, const qbyte *str); extern void (*Draw_Alt_String) (int x, int y, const qbyte *str); @@ -33,7 +34,7 @@ extern void (*Draw_TransPicTranslate) (int x, int y, int width, int height, q extern void (*Draw_ConsoleBackground) (int lines); extern void (*Draw_EditorBackground) (int lines); extern void (*Draw_TileClear) (int x, int y, int w, int h); -extern void (*Draw_Fill) (int x, int y, int w, int h, int c); +extern void (*Draw_Fill) (int x, int y, int w, int h, unsigned int c); extern void (*Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b); extern void (*Draw_FadeScreen) (void); extern void (*Draw_BeginDisc) (void); @@ -129,6 +130,7 @@ typedef struct { void (*Draw_ReInit) (void); void (*Draw_Character) (int x, int y, unsigned int num); void (*Draw_ColouredCharacter) (int x, int y, unsigned int num); + void (*Draw_TinyCharacter) (int x, int y, unsigned int num); void (*Draw_String) (int x, int y, const qbyte *str); void (*Draw_Alt_String) (int x, int y, const qbyte *str); void (*Draw_Crosshair) (void); @@ -141,7 +143,7 @@ typedef struct { void (*Draw_ConsoleBackground) (int lines); void (*Draw_EditorBackground) (int lines); void (*Draw_TileClear) (int x, int y, int w, int h); - void (*Draw_Fill) (int x, int y, int w, int h, int c); + void (*Draw_Fill) (int x, int y, int w, int h, unsigned int c); void (*Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b); void (*Draw_FadeScreen) (void); void (*Draw_BeginDisc) (void); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 1cca2e3cc..519367329 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3313,10 +3313,15 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p } } + model = cl.model_precache[src->modelindex]; + if (oldent && model->particletrail >= 0) + { + if (P_ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) + P_ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); + } ent->v->entnum = src->number; ent->v->modelindex = src->modelindex; - model = cl.model_precache[src->modelindex]; // ent->v->bitmask = src->bitmask; ent->v->flags = src->flags; // ent->v->effects = src->effects; @@ -3354,7 +3359,7 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p if (model) { - if (model->flags & EF_ROTATE) + if ((flags & RSES_AUTOROTATE) && (model->flags & EF_ROTATE)) { ent->v->angles[0] = 0; ent->v->angles[1] = 100*servertime; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index f58e92a0a..38f15c39f 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -719,6 +719,7 @@ void (*Draw_ReInit) (void); void (*Draw_Character) (int x, int y, unsigned int num); void (*Draw_ColouredCharacter) (int x, int y, unsigned int num); void (*Draw_String) (int x, int y, const qbyte *str); +void (*Draw_TinyCharacter) (int x, int y, unsigned int num); void (*Draw_Alt_String) (int x, int y, const qbyte *str); void (*Draw_Crosshair) (void); void (*Draw_DebugChar) (qbyte num); @@ -730,7 +731,7 @@ void (*Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *image, qbyte void (*Draw_ConsoleBackground) (int lines); void (*Draw_EditorBackground) (int lines); void (*Draw_TileClear) (int x, int y, int w, int h); -void (*Draw_Fill) (int x, int y, int w, int h, int c); +void (*Draw_Fill) (int x, int y, int w, int h, unsigned int c); void (*Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b); void (*Draw_FadeScreen) (void); void (*Draw_BeginDisc) (void); @@ -812,6 +813,7 @@ rendererinfo_t dedicatedrendererinfo = { NULL, //Draw_Init; NULL, //Draw_Character; NULL, //Draw_ColouredCharacter; + NULL, //Draw_TinyCharacter; NULL, //Draw_String; NULL, //Draw_Alt_String; NULL, //Draw_Crosshair; @@ -919,6 +921,7 @@ rendererinfo_t softwarerendererinfo = { SWDraw_Init, SWDraw_Character, SWDraw_ColouredCharacter, + SWDraw_TinyCharacter, SWDraw_String, SWDraw_Alt_String, SWDraw_Crosshair, @@ -1012,6 +1015,7 @@ rendererinfo_t openglrendererinfo = { GLDraw_ReInit, GLDraw_Character, GLDraw_ColouredCharacter, + GLDraw_TinyCharacter, GLDraw_String, GLDraw_Alt_String, GLDraw_Crosshair, @@ -1459,6 +1463,7 @@ void R_SetRenderer(int wanted) Draw_Character = ri->Draw_Character; Draw_ColouredCharacter = ri->Draw_ColouredCharacter; Draw_String = ri->Draw_String; + Draw_TinyCharacter = ri->Draw_TinyCharacter; Draw_Alt_String = ri->Draw_Alt_String; Draw_Crosshair = ri->Draw_Crosshair; Draw_DebugChar = ri->Draw_DebugChar; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 9f3660068..02a63e002 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -70,6 +70,9 @@ cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1 int sb_updates; // if >= vid.numpages, no update needed +int sb_hexen2_cur_item;//hexen2 hud +qboolean sb_hexen2_extra_info;//show the extra stuff +float sb_hexen2_item_time; #define STAT_MINUS 10 // num frame for '-' stats digit mpic_t *sb_nums[2][11]; @@ -808,6 +811,35 @@ void Sbar_ShowScores (void) sb_updates = 0; } +void Sbar_Hexen2InvLeft_f(void) +{ + sb_hexen2_item_time = realtime; + sb_hexen2_cur_item--; + if (sb_hexen2_cur_item < 0) + sb_hexen2_cur_item = 14; +} +void Sbar_Hexen2InvRight_f(void) +{ + sb_hexen2_item_time = realtime; + sb_hexen2_cur_item++; + if (sb_hexen2_cur_item > 14) + sb_hexen2_cur_item = 0; +} +void Sbar_Hexen2InvUse_f(void) +{ + Cbuf_AddText(va("impulse %d\n", 100+sb_hexen2_cur_item), Cmd_ExecLevel); +} + +void Sbar_Hexen2ShowInfo_f(void) +{ + sb_hexen2_extra_info = true; +} + +void Sbar_Hexen2DontShowInfo_f(void) +{ + sb_hexen2_extra_info = false; +} + /* =============== Sbar_DontShowScores @@ -889,6 +921,9 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. sb_nums[1][i] = Sbar_PicFromWad (va("anum_%i",i)); } + if (sb_nums[0][0] && sb_nums[0][0]->width < 13) + sbar_hexen2 = true; + sb_nums[0][10] = Sbar_PicFromWad ("num_minus"); sb_nums[1][10] = Sbar_PicFromWad ("anum_minus"); @@ -1010,6 +1045,15 @@ void Sbar_Init (void) Cmd_AddCommand ("+showteamscores", Sbar_ShowTeamScores); Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores); + + //stuff to get hexen2 working out-of-the-box + Cmd_AddCommand ("invleft", Sbar_Hexen2InvLeft_f); + Cmd_AddCommand ("invright", Sbar_Hexen2InvRight_f); + Cmd_AddCommand ("invuse", Sbar_Hexen2InvUse_f); + Cmd_AddCommand ("+showinfo", Sbar_Hexen2ShowInfo_f); + Cmd_AddCommand ("-showinfo", Sbar_Hexen2DontShowInfo_f); + Cbuf_AddText("alias +crouch \"impulse 22\"\n", RESTRICT_LOCAL); + Cbuf_AddText("alias -crouch \"impulse 22\"\n", RESTRICT_LOCAL); } @@ -1076,6 +1120,56 @@ void Sbar_DrawFunString (int x, int y, char *str) Draw_FunString (sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); } +void Draw_TinyString (int x, int y, const qbyte *str) +{ + float xstart = x; + while (*str) + { + if (*str == '\n') + { + x = xstart; + y += 6; + str++; + continue; + } + if (Draw_TinyCharacter) + Draw_TinyCharacter (x, y, *str); +// Draw_Character (x, y, *str); + str++; + x += 6; + } +} +void Sbar_DrawTinyString (int x, int y, char *str) +{ + Draw_TinyString (sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); +} + +void Sbar_FillPC (int x, int y, int w, int h, unsigned int pcolour) +{ + if (pcolour >= 16) + { + Draw_FillRGB (x, y, w, h, (pcolour&0xff)/255.0f, ((pcolour&0xff00)>>8)/255.0f, ((pcolour&0xff0000)>>16)/255.0f); + } + else + { + pcolour = Sbar_ColorForMap(pcolour); + Draw_Fill (x, y, w, h, pcolour); + } +} +static void Sbar_FillPCDark (int x, int y, int w, int h, unsigned int pcolour) +{ + if (pcolour >= 16) + { + Draw_FillRGB (x, y, w, h, (pcolour&0xff)/1024.0f, ((pcolour&0xff00)>>8)/1024.0f, ((pcolour&0xff0000)>>17)/1024.0f); + } + else + { + pcolour = Sbar_ColorForMap(pcolour)-1; + Draw_Fill (x, y, w, h, pcolour); + } +} + + /* ============= Sbar_itoa @@ -1164,6 +1258,34 @@ void Sbar_DrawNum (int x, int y, int num, int digits, int color) } } +void Sbar_Hexen2DrawNum (int x, int y, int num, int digits) +{ + char str[12]; + char *ptr; + int l, frame; + + l = Sbar_itoa (num, str); + ptr = str; + if (l > digits) + ptr += (l-digits); + + //hexen2 hud has it centered + if (l < digits) + x += ((digits-l)*13)/2; + + while (*ptr) + { + if (*ptr == '-') + frame = STAT_MINUS; + else + frame = *ptr -'0'; + + Sbar_DrawTransPic (x,y,sb_nums[0][frame]); + x += 13; + ptr++; + } +} + //============================================================================= int fragsort[MAX_CLIENTS]; @@ -1291,8 +1413,11 @@ void Sbar_SortTeams (void) } } -int Sbar_ColorForMap (int m) +unsigned int Sbar_ColorForMap (unsigned int m) { + if (m >= 16) + return m; + m = (m < 0) ? 0 : ((m > 13) ? 13 : m); m *= 16; @@ -1567,16 +1692,12 @@ void Sbar_DrawFrags (void) // draw background top = Sbar_TopColour(s); bottom = Sbar_BottomColour(s); - top = (top < 0) ? 0 : ((top > 13) ? 13 : top); - bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom); - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); // Draw_Fill (xofs + x*8 + 10, y, 28, 4, top); // Draw_Fill (xofs + x*8 + 10, y+4, 28, 3, bottom); - Draw_Fill (sbar_rect.x+x*8 + 10, sbar_rect.y+y, 28, 4, top); - Draw_Fill (sbar_rect.x+x*8 + 10, sbar_rect.y+y+4, 28, 3, bottom); + Sbar_FillPC (sbar_rect.x+x*8 + 10, sbar_rect.y+y, 28, 4, top); + Sbar_FillPC (sbar_rect.x+x*8 + 10, sbar_rect.y+y+4, 28, 3, bottom); // draw number f = s->frags; @@ -1790,6 +1911,199 @@ void Sbar_DrawScoreboard (void) sb_updates = 0; } + +void Sbar_Hexen2DrawItem(int pnum, int x, int y, int itemnum) +{ + int num; + Sbar_DrawPic(x, y, Draw_CachePic(va("gfx/arti%02d.lmp", itemnum))); + + num = cl.stats[pnum][STAT_H2_CNT_TORCH+itemnum]; + if(num > 0) + { + if (num >= 10) + Sbar_DrawPic(x+20, y+21, Draw_CachePic(va("gfx/artinum%d.lmp", num/10))); + Sbar_DrawPic(x+20+4, y+21, Draw_CachePic(va("gfx/artinum%d.lmp", num%10))); + } +} + +void Sbar_Hexen2DrawInventory(int pnum) +{ + int i; + int x, y=-37; + + if (sb_hexen2_item_time+3 < realtime) + return; + +#if 1 + for (i = 0, x=320/2-114; i < 7; i++, x+=33) + { + if ((sb_hexen2_cur_item-3+i+30)%15 == sb_hexen2_cur_item) + Sbar_DrawTransPic(x+9, y-12, Draw_CachePic("gfx/artisel.lmp")); + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item-3+i+30)%15); + } +#else + for (i = 0, x=320/2; i < 3; i++, x+=33) + { + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item+1+i)%15); + } + for (i = 0, x=320/2-33; i < 3; i++, x-=33) + { + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item-1-i+45)%15); + } +#endif +} + +void Sbar_Hexen2DrawExtra (int pnum) +{ + unsigned int i, slot; + unsigned int pclass; + int ringpos[] = {6, 44, 81, 119}; + char *ringimages[] = {"gfx/ring_f.lmp", "gfx/ring_w.lmp", "gfx/ring_t.lmp", "gfx/ring_r.lmp"}; + float val; + char *pclassname[] = { + "Unknown", + "Barbarian", + "Crusader", + "Paladin", + "Assasin" + }; + + if (!sb_hexen2_extra_info) + { + sbar_rect.y -= 46-SBAR_HEIGHT; + return; + } + + pclass = cl.stats[pnum][STAT_H2_PLAYERCLASS]; + if (pclass >= sizeof(pclassname)/sizeof(pclassname[0])) + pclass = sizeof(pclassname)/sizeof(pclassname[0]) - 1; + + + //adjust it so there's space + sbar_rect.y -= 46+98-SBAR_HEIGHT; + + Sbar_DrawPic(0, 46, Draw_SafeCachePic("gfx/btmbar1.lmp")); + Sbar_DrawPic(160, 46, Draw_SafeCachePic("gfx/btmbar2.lmp")); + + Sbar_DrawTinyString (11, 48, pclassname[pclass]); + + Sbar_DrawTinyString (11, 58, va("int")); + Sbar_DrawTinyString (33, 58, va("%02d", cl.stats[pnum][STAT_H2_INTELLIGENCE])); + + Sbar_DrawTinyString (11, 64, va("wis")); + Sbar_DrawTinyString (33, 64, va("%02d", cl.stats[pnum][STAT_H2_WISDOM])); + + Sbar_DrawTinyString (11, 70, va("dex")); + Sbar_DrawTinyString (33, 70, va("%02d", cl.stats[pnum][STAT_H2_DEXTERITY])); + + + Sbar_DrawTinyString (58, 58, va("str")); + Sbar_DrawTinyString (80, 58, va("%02d", cl.stats[pnum][STAT_H2_STRENGTH])); + + Sbar_DrawTinyString (58, 64, va("lvl")); + Sbar_DrawTinyString (80, 64, va("%02d", cl.stats[pnum][STAT_H2_LEVEL])); + + Sbar_DrawTinyString (58, 70, va("exp")); + Sbar_DrawTinyString (80, 70, va("%06d", cl.stats[pnum][STAT_H2_EXPERIENCE])); + + Sbar_DrawTinyString (11, 79, va("abilities")); + if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<22)) + Sbar_DrawTinyString (8, 89, va("ability 1")); + if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<23)) + Sbar_DrawTinyString (8, 96, va("ability 2")); + + for (i = 0; i < 4; i++) + { + if (cl.stats[pnum][STAT_H2_ARMOUR1+i] > 0) + { + Sbar_DrawPic (164+i*40, 115, Draw_SafeCachePic(va("gfx/armor%d.lmp", i+1))); + Sbar_DrawTinyString (168+i*40, 136, va("+%d", cl.stats[pnum][STAT_H2_ARMOUR1+i])); + } + } + for (i = 0; i < 4; i++) + { + if (cl.stats[pnum][STAT_H2_FLIGHT_T+i] > 0) + { + Sbar_DrawPic (ringpos[i], 119, Draw_SafeCachePic(va("gfx/ring_f.lmp", i+1))); + val = cl.stats[pnum][STAT_H2_FLIGHT_T+i]; + if (val > 100) + val = 100; + if (val < 0) + val = 0; + Sbar_DrawPic(ringpos[i]+29 - (int)(26 * (val/(float)100)),142,Draw_CachePic("gfx/ringhlth.lmp")); + Sbar_DrawPic(ringpos[i]+29, 142, Draw_CachePic("gfx/rhlthcvr.lmp")); + } + } + + slot = 0; + for (i = 0; i < 8; i++) + { + if (cl.statsstr[pnum][STAT_H2_PUZZLE1+i]) + { + Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, Draw_SafeCachePic(va("gfx/puzzle/%s.lmp", cl.statsstr[pnum][STAT_H2_PUZZLE1+i]))); + slot++; + } + } + + Sbar_DrawPic(134, 50, Draw_CachePic(va("gfx/cport%d.lmp", pclass))); +} + +void Sbar_Hexen2DrawBasic(int pnum) +{ + int chainpos; + int val, maxval; + Sbar_DrawPic(0, 0, Draw_CachePic("gfx/topbar1.lmp")); + Sbar_DrawPic(160, 0, Draw_CachePic("gfx/topbar2.lmp")); + Sbar_DrawTransPic(0, -23, Draw_CachePic("gfx/topbumpl.lmp")); + Sbar_DrawTransPic(138, -8, Draw_CachePic("gfx/topbumpm.lmp")); + Sbar_DrawTransPic(269, -23, Draw_CachePic("gfx/topbumpr.lmp")); + + //mana1 + maxval = cl.stats[pnum][STAT_H2_MAXMANA]; + val = cl.stats[pnum][STAT_H2_BLUEMANA]; + val = bound(0, val, maxval); + Sbar_DrawTinyString(201, 22, va("%03d", val)); + if(val) + { + Sbar_DrawPic(190, 26-(int)((val*18.0)/(float)maxval+0.5), Draw_CachePic("gfx/bmana.lmp")); + Sbar_DrawPic(190, 27, Draw_CachePic("gfx/bmanacov.lmp")); + } + + //mana2 + maxval = cl.stats[pnum][STAT_H2_MAXMANA]; + val = cl.stats[pnum][STAT_H2_GREENMANA]; + val = bound(0, val, maxval); + Sbar_DrawTinyString(243, 22, va("%03d", val)); + if(val) + { + Sbar_DrawPic(232, 26-(int)((val*18.0)/(float)maxval+0.5), Draw_CachePic("gfx/gmana.lmp")); + Sbar_DrawPic(232, 27, Draw_CachePic("gfx/gmanacov.lmp")); + } + + + //health + val = cl.stats[pnum][STAT_HEALTH]; + if (val < -99) + val = -99; + Sbar_Hexen2DrawNum(58, 14, val, 3); + + //armour + val = 0; + Sbar_Hexen2DrawNum(105, 14, val, 2); + +// SetChainPosition(cl.v.health, cl.v.max_health); + chainpos = (195.0f*cl.stats[pnum][STAT_HEALTH]) / cl.stats[pnum][STAT_H2_MAXHEALTH]; + if (chainpos < 0) + chainpos = 0; + Sbar_DrawPic(45+((int)chainpos&7), 38, Draw_CachePic("gfx/hpchain.lmp")); + Sbar_DrawPic(45+(int)chainpos, 36, Draw_CachePic("gfx/hpgem.lmp")); + Sbar_DrawPic(43, 36, Draw_CachePic("gfx/chnlcov.lmp")); + Sbar_DrawPic(267, 36, Draw_CachePic("gfx/chnrcov.lmp")); + + + Sbar_Hexen2DrawItem(pnum, 144, 3, sb_hexen2_cur_item); +} + /* =============== Sbar_Draw @@ -1849,6 +2163,17 @@ void Sbar_Draw (void) } } + if (sbar_hexen2) + { + Sbar_Hexen2DrawExtra(pnum); + Sbar_Hexen2DrawBasic(pnum); + Sbar_Hexen2DrawInventory(pnum); + + if (cl.deathmatch) + Sbar_MiniDeathmatchOverlay (); + continue; + } + if (sbarfailed) //files failed to load. { if (cl.stats[pnum][STAT_HEALTH] <= 0) //when dead, show nothing @@ -1939,7 +2264,7 @@ void Sbar_Draw (void) - if (sb_lines > 0) + if (sb_lines > 0 && cl.deathmatch) Sbar_MiniDeathmatchOverlay (); { @@ -2125,10 +2450,10 @@ ping time frags name else \ { \ if (largegame) \ - Draw_Fill ( x, y+1, 40, 3, top); \ + Sbar_FillPC ( x, y+1, 40, 3, top); \ else \ - Draw_Fill ( x, y, 40, 4, top); \ - Draw_Fill ( x, y+4, 40, 4, bottom); \ + Sbar_FillPC ( x, y, 40, 4, top); \ + Sbar_FillPC ( x, y+4, 40, 4, bottom); \ \ f = s->frags; \ sprintf (num, "%3i",f); \ @@ -2318,7 +2643,7 @@ if (showcolumns & (1<userinfo, "team"), sizeof(team)); if (!(strcmp("red", team))) - background_color = 72; // forced red + background_color = 4; // forced red else if (!(strcmp("blue", team))) - background_color = 216; // forced blue + background_color = 13; // forced blue else - background_color = bottom - 1; + background_color = bottom; - Draw_Fill (startx - 2, y, rank_width - 3, skip, background_color); + Sbar_FillPCDark (startx - 2, y, rank_width - 3, skip, background_color); } else Draw_Fill (startx - 2, y, rank_width - 3, skip, 2); @@ -2552,14 +2875,12 @@ void Sbar_ChatModeOverlay(void) // draw background top = Sbar_TopColour(s); bottom = Sbar_BottomColour(s); - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); if (largegame) - Draw_Fill ( x, y+1, 8*4, 3, top); + Sbar_FillPC ( x, y+1, 8*4, 3, top); else - Draw_Fill ( x, y, 8*4, 4, top); - Draw_Fill ( x, y+4, 8*4, 4, bottom); + Sbar_FillPC ( x, y, 8*4, 4, top); + Sbar_FillPC ( x, y+4, 8*4, 4, bottom); if (cl.spectator && k == Cam_TrackNum(0)) { @@ -2662,11 +2983,9 @@ void Sbar_MiniDeathmatchOverlay (void) // draw ping top = Sbar_TopColour(s); bottom = Sbar_BottomColour(s); - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); - Draw_Fill ( x, y+1, 40, 3, top); - Draw_Fill ( x, y+4, 40, 4, bottom); + Sbar_FillPC ( x, y+1, 40, 3, top); + Sbar_FillPC ( x, y+4, 40, 4, bottom); // draw number f = s->frags; diff --git a/engine/client/sbar.h b/engine/client/sbar.h index 9ccf99a2b..1def9e543 100644 --- a/engine/client/sbar.h +++ b/engine/client/sbar.h @@ -46,4 +46,4 @@ void Sbar_SortFrags (qboolean includespec); void Sbar_Start (void); void Sbar_Flush (void); -int Sbar_ColorForMap (int m); +unsigned int Sbar_ColorForMap (unsigned int m); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 81b1343c3..2fe11106b 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -1772,51 +1772,66 @@ char *TP_MapName (void) ============================================================================= */ -int cl_teamtopcolor = -1; -int cl_teambottomcolor = -1; -int cl_enemytopcolor = -1; -int cl_enemybottomcolor = -1; +unsigned int cl_teamtopcolor = ~0; +unsigned int cl_teambottomcolor = ~0; +unsigned int cl_enemytopcolor = ~0; +unsigned int cl_enemybottomcolor = ~0; + +static unsigned int TP_ForceColour(char *col) +{ + float rgb[3]; + unsigned int bitval; + if (!strcmp(col, "off")) + return ~0; + if (!strncmp(col, "0x", 2)) + { + bitval = 0x01000000 | strtoul(col+2, NULL, 16); + if (bitval == ~0) + bitval = 0x01ffffff; + return bitval; + } + if (strchr(col, ' ')) + { + SCR_StringToRGB(col, rgb, 1); + bitval = ((unsigned char)rgb[0]<<0) | ((unsigned char)rgb[1]<<8) | ((unsigned char)rgb[2]<<16) | (0xff<<24); + if (bitval == ~0) + bitval = 0x01ffffff; + return bitval; + } + return atoi(col); +} static void TP_TeamColor_f (void) { - int top, bottom; + unsigned int top, bottom; int i; if (Cmd_Argc() == 1) { - if (cl_teamtopcolor < 0) - Com_Printf ("\"teamcolor\" is \"off\"\n"); + + Com_Printf ("\"teamcolor\" is \""); + if (cl_teamtopcolor == ~0) + Com_Printf ("off"); else - Com_Printf ("\"teamcolor\" is \"%i %i\"\n", - cl_teamtopcolor, - cl_teambottomcolor); - return; - } - - if (!strcmp(Cmd_Argv(1), "off")) - { - cl_teamtopcolor = -1; - cl_teambottomcolor = -1; - if (qrenderer>QR_NONE) //make sure we have the renderer initialised... - for (i = 0; i < MAX_CLIENTS; i++) - CL_NewTranslation(i); + Com_Printf (cl_teamtopcolor>=16?"0x%06x":"%i", cl_teamtopcolor&0x00ffffff); + if (cl_teamtopcolor != cl_teambottomcolor) + { + if (cl_teambottomcolor == ~0) + Com_Printf (" off"); + else + Com_Printf (cl_teambottomcolor>=16?" 0x%06x":" %i", cl_teambottomcolor&0x00ffffff); + } + Com_Printf ("\"\n"); return; } + top = TP_ForceColour(Cmd_Argv(1)); if (Cmd_Argc() == 2) - top = bottom = atoi(Cmd_Argv(1)); + bottom = top; else { - top = atoi(Cmd_Argv(1)); - bottom = atoi(Cmd_Argv(2)); + bottom = TP_ForceColour(Cmd_Argv(2)); } - top &= 15; - if (top > 13) - top = 13; - bottom &= 15; - if (bottom > 13) - bottom = 13; - // if (top != cl_teamtopcolor || bottom != cl_teambottomcolor) { cl_teamtopcolor = top; @@ -1830,43 +1845,33 @@ static void TP_TeamColor_f (void) static void TP_EnemyColor_f (void) { - int top, bottom; + unsigned int top, bottom; int i; if (Cmd_Argc() == 1) { - if (cl_enemytopcolor < 0) - Com_Printf ("\"enemycolor\" is \"off\"\n"); + Com_Printf ("\"teamcolor\" is \""); + if (cl_enemytopcolor == ~0) + Com_Printf ("off"); else - Com_Printf ("\"enemycolor\" is \"%i %i\"\n", - cl_enemytopcolor, - cl_enemybottomcolor); - return; - } - - if (!strcmp(Cmd_Argv(1), "off")) - { - cl_enemytopcolor = -1; - cl_enemybottomcolor = -1; - if (qrenderer>QR_NONE) //make sure we have the renderer initialised... - for (i = 0; i < MAX_CLIENTS; i++) - CL_NewTranslation(i); + Com_Printf (cl_enemytopcolor>=16?"0x%06x":"%i", cl_enemytopcolor&0x00ffffff); + if (cl_enemytopcolor != cl_enemybottomcolor) + { + if (cl_enemybottomcolor == ~0) + Com_Printf (" off"); + else + Com_Printf (cl_enemybottomcolor>=16?" 0x%06x":" %i", cl_enemybottomcolor&0x00ffffff); + } + Com_Printf ("\"\n"); return; } + top = TP_ForceColour(Cmd_Argv(1)); if (Cmd_Argc() == 2) - top = bottom = atoi(Cmd_Argv(1)); + bottom = top; else { - top = atoi(Cmd_Argv(1)); - bottom = atoi(Cmd_Argv(2)); + bottom = TP_ForceColour(Cmd_Argv(2)); } - - top &= 15; - if (top > 13) - top = 13; - bottom &= 15; - if (bottom > 13) - bottom = 13; // if (top != cl_enemytopcolor || bottom != cl_enemybottomcolor) { diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 7455d4143..a0b58a61d 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -417,49 +417,26 @@ STAT_H2_INVENTORY, STAT_H2_RINGS_ACTIVE, STAT_H2_RINGS_LOW, -STAT_H2_AMULET, -STAT_H2_BRACER, -STAT_H2_BREASTPLATE, -STAT_H2_HELMET, +STAT_H2_ARMOUR1, +STAT_H2_ARMOUR2, +STAT_H2_ARMOUR3, +STAT_H2_ARMOUR4, STAT_H2_FLIGHT_T, STAT_H2_WATER_T, STAT_H2_TURNING_T, STAT_H2_REGEN_T, -STAT_H2_PUZZLE1A, -STAT_H2_PUZZLE1B, -STAT_H2_PUZZLE1C, -STAT_H2_PUZZLE1D, -STAT_H2_PUZZLE2A, -STAT_H2_PUZZLE2B, -STAT_H2_PUZZLE2C, -STAT_H2_PUZZLE2D, -STAT_H2_PUZZLE3A, -STAT_H2_PUZZLE3B, -STAT_H2_PUZZLE3C, -STAT_H2_PUZZLE3D, -STAT_H2_PUZZLE4A, -STAT_H2_PUZZLE4B, -STAT_H2_PUZZLE4C, -STAT_H2_PUZZLE4D, -STAT_H2_PUZZLE5A, -STAT_H2_PUZZLE5B, -STAT_H2_PUZZLE5C, -STAT_H2_PUZZLE5D, -STAT_H2_PUZZLE6A, -STAT_H2_PUZZLE6B, -STAT_H2_PUZZLE6C, -STAT_H2_PUZZLE6D, -STAT_H2_PUZZLE7A, -STAT_H2_PUZZLE7B, -STAT_H2_PUZZLE7C, -STAT_H2_PUZZLE7D, -STAT_H2_PUZZLE8A, -STAT_H2_PUZZLE8B, -STAT_H2_PUZZLE8C, -STAT_H2_PUZZLE8D, +STAT_H2_PUZZLE1, +STAT_H2_PUZZLE2, +STAT_H2_PUZZLE3, +STAT_H2_PUZZLE4, +STAT_H2_PUZZLE5, +STAT_H2_PUZZLE6, +STAT_H2_PUZZLE7, +STAT_H2_PUZZLE8, STAT_H2_MAXHEALTH, STAT_H2_MAXMANA, STAT_H2_FLAGS, +STAT_H2_PLAYERCLASS, diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index a93dd4b89..d070387dc 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1640,11 +1640,11 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) else skinstart = (daliasskintype_t *)(pq1inmodel+1); if( mod->flags & EF_HOLEY ) - skintranstype = 3; + skintranstype = 3; //hexen2 else if( mod->flags & EF_TRANSPARENT ) - skintranstype = 2; + skintranstype = 2; //hexen2 else if( mod->flags & EF_SPECIAL_TRANS ) - skintranstype = 4; + skintranstype = 4; //hexen2 else skintranstype = 0; diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 8549c4928..209224fb5 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -113,7 +113,8 @@ typedef struct { typedef struct { char name[MAX_QPATH]; galiastexnum_t texnum; - int colour; + unsigned int tcolour; + unsigned int bcolour; int skinnum; bucket_t bucket; } galiascolourmapped_t; diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 51e4259fc..4db74d560 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -893,7 +893,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur galiastexnum_t *texnums; int frame; - int tc, bc; + unsigned int tc, bc; qboolean forced; if ((e->model->engineflags & MDLF_NOTREPLACEMENTS) && !ruleset_allow_sensative_texture_replacements.value) @@ -922,10 +922,8 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur int tinwidth, tinheight; char *skinname; qbyte *original; - int cc; galiascolourmapped_t *cm; char hashname[512]; - cc = (tc<<4)|bc; // if (e->scoreboard->skin->cachedbpp @@ -962,7 +960,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur for (cm = Hash_Get(&skincolourmapped, skinname); cm; cm = Hash_GetNext(&skincolourmapped, skinname, cm)) { - if (cm->colour == cc && cm->skinnum == e->skinnum) + if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum) { return &cm->texnum; } @@ -987,7 +985,8 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur cm = BZ_Malloc(sizeof(*cm)); Q_strncpyz(cm->name, skinname, sizeof(cm->name)); Hash_Add(&skincolourmapped, cm->name, cm, &cm->bucket); - cm->colour = cc; + cm->tcolour = tc; + cm->bcolour = bc; cm->skinnum = e->skinnum; cm->texnum.fullbright = 0; cm->texnum.base = 0; @@ -1061,7 +1060,6 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur if (original) { int i, j; - qbyte translate[256]; unsigned translate32[256]; static unsigned pixels[512*512]; unsigned *out; @@ -1104,29 +1102,44 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur if (scaled_height > gl_max_size.value) scaled_height = gl_max_size.value; //whoops, we made it too big - for (i=0 ; i<256 ; i++) - translate[i] = i; - - tc<<=4; - bc<<=4; - - for (i=0 ; i<16 ; i++) { - if (tc < 128) // the artists made some backwards ranges. sigh. - translate[TOP_RANGE+i] = tc+i; - else - translate[TOP_RANGE+i] = tc+15-i; + for (i=0 ; i<256 ; i++) + translate32[i] = d_8to24rgbtable[i]; - if (bc < 128) - translate[BOTTOM_RANGE+i] = bc+i; - else - translate[BOTTOM_RANGE+i] = bc+15-i; + for (i = 0; i < 16; i++) + { + if (tc >= 16) + { + //assumption: row 0 is pure white. + translate32[TOP_RANGE+i] = 0xff000000| + (((((tc&0x0000ff)>> 0)*((d_8to24rgbtable[i]&0x0000ff)>> 0))>>8)) | + (((((tc&0x00ff00)>> 8)*((d_8to24rgbtable[i]&0x00ff00)>> 8))>>8)<<8) | + (((((tc&0xff0000)>>16)*((d_8to24rgbtable[i]&0xff0000)>>16))>>8)<<16); + } + else + { + if (tc < 8) + translate32[TOP_RANGE+i] = d_8to24rgbtable[(tc<<4)+i]; + else + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(tc<<4)+15-i]; + } + if (bc >= 16) + { + translate32[BOTTOM_RANGE+i] = 0xff000000| + (((((bc&0x0000ff)>> 0)*((d_8to24rgbtable[i]&0x0000ff)>> 0))>>8)) | + (((((bc&0x00ff00)>> 8)*((d_8to24rgbtable[i]&0x00ff00)>> 8))>>8)<<8) | + (((((bc&0xff0000)>>16)*((d_8to24rgbtable[i]&0xff0000)>>16))>>8)<<16); + } + else + { + if (bc < 8) + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(bc<<4)+i]; + else + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(bc<<4)+15-i]; + } + } } - - for (i=0 ; i<256 ; i++) - translate32[i] = d_8to24rgbtable[translate[i]]; - out = pixels; fracstep = tinwidth*0x10000/scaled_width; for (i=0 ; imodel->flags & EF_ROTATE) && cl.hexen2pickups) + { + shadelight[0] = shadelight[1] = shadelight[2] = + ambientlight[0] = ambientlight[1] = ambientlight[2] = 128+sin(cl.time*4)*64; + } if ((e->drawflags & MLS_MASKIN) == MLS_ABSLIGHT) { shadelight[0] = shadelight[1] = shadelight[2] = e->abslight; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index a65046933..1bee35ceb 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -283,6 +283,7 @@ int r_dlighttexture; void R_FetchTopColour(int *retred, int *retgreen, int *retblue) { int i; + if (currententity->scoreboard) { i = currententity->scoreboard->ttopcolor; @@ -312,6 +313,7 @@ void R_FetchTopColour(int *retred, int *retgreen, int *retblue) void R_FetchBottomColour(int *retred, int *retgreen, int *retblue) { int i; + if (currententity->scoreboard) { i = currententity->scoreboard->tbottomcolor; diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 1002b4ecb..3e0ab9dc6 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -80,7 +80,7 @@ mpic_t *draw_disc; mpic_t *draw_backtile; int translate_texture; -int char_texture, char_tex2, default_char_texture; +int char_texture, char_tex2, default_char_texture, char_texturetiny; int missing_texture; //texture used when one is missing. int cs_texture; // crosshair texture extern int detailtexture; @@ -976,6 +976,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); gl->th = 1; glmenu_numcachepics++; + char_texturetiny = 0; TRACE(("dbg: GLDraw_ReInit: W_SafeGetLumpName\n")); tinyfont = W_SafeGetLumpName ("tinyfont"); if (tinyfont) @@ -987,7 +988,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); glmenu_cachepics[glmenu_numcachepics].pic.width = 128; glmenu_cachepics[glmenu_numcachepics].pic.height = 32; gl = (glpic_t *)&glmenu_cachepics[glmenu_numcachepics].pic.data; - gl->texnum = GL_LoadTexture ("tinyfont", 128, 32, tinyfont, false, true); + char_texturetiny = gl->texnum = GL_LoadTexture ("tinyfont", 128, 32, tinyfont, false, true); gl->sl = 0; gl->tl = 0; gl->sh = 1; @@ -1008,6 +1009,8 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); glmenu_cachepics[glmenu_numcachepics].pic.height = bigfont->height; gl = (glpic_t *)&glmenu_cachepics[glmenu_numcachepics].pic.data; gl->texnum = GL_LoadTexture ("gfx/menu/bigfont.lmp", bigfont->width, bigfont->height, data, false, true); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl->sl = 0; gl->tl = 0; gl->sh = 1; @@ -1219,6 +1222,58 @@ void GL_DrawMesh(mesh_t *msh, int texturenum) } +void GLDraw_TinyCharacter (int x, int y, unsigned int num) +{ + int row, col; + float frow, fcol, sizex, sizey; + + if (y <= -6) + return; // totally off screen + + num &= 127; + + if(num <= 32) + return; + else if(num >= 'a' && num <= 'z') + num -= 64; + else if(num > '_') + return; + else + num -= 32; + + row = num>>4; + col = num&15; + + sizex = 0.0625; + sizey = 0.25; + frow = row*sizey; + fcol = col*sizex; + draw_mesh_xyz[0][0] = x; + draw_mesh_xyz[0][1] = y; + draw_mesh_st[0][0] = fcol; + draw_mesh_st[0][1] = frow; + + draw_mesh_xyz[1][0] = x+8; + draw_mesh_xyz[1][1] = y; + draw_mesh_st[1][0] = fcol+sizex; + draw_mesh_st[1][1] = frow; + + draw_mesh_xyz[2][0] = x+8; + draw_mesh_xyz[2][1] = y+8; + draw_mesh_st[2][0] = fcol+sizex; + draw_mesh_st[2][1] = frow+sizey; + + draw_mesh_xyz[3][0] = x; + draw_mesh_xyz[3][1] = y+8; + draw_mesh_st[3][0] = fcol; + draw_mesh_st[3][1] = frow+sizey; + + qglEnable(GL_BLEND); + qglDisable(GL_ALPHA_TEST); + + GL_DrawMesh(&draw_mesh, char_texturetiny); +} + /* ================ Draw_Character @@ -1241,8 +1296,6 @@ void GLDraw_Character (int x, int y, unsigned int num) if (num == 32) return; // space - num &= 255; - row = num>>4; col = num&15; @@ -1977,23 +2030,26 @@ Draw_Fill Fills a box of pixels with a single color ============= */ -void GLDraw_Fill (int x, int y, int w, int h, int c) +void GLDraw_Fill (int x, int y, int w, int h, unsigned int c) { + unsigned int r, g, b; extern qboolean gammaworks; - if (gammaworks) + + r = host_basepal[c*3]; + g = host_basepal[c*3+1]; + b = host_basepal[c*3+2]; + + if (!gammaworks) { - GLDraw_FillRGB (x, y, w, h, - host_basepal[c*3]/255.0, - host_basepal[c*3+1]/255.0, - host_basepal[c*3+2]/255.0); - } - else - { - GLDraw_FillRGB (x, y, w, h, - gammatable[host_basepal[c*3]]/255.0, - gammatable[host_basepal[c*3+1]]/255.0, - gammatable[host_basepal[c*3+2]]/255.0); + r = gammatable[r]; + g = gammatable[r]; + b = gammatable[r]; } + + GLDraw_FillRGB (x, y, w, h, + r/255.0, + g/255.0, + b/255.0); } //============================================================================= diff --git a/engine/gl/gl_draw.h b/engine/gl/gl_draw.h index 46aacb2e0..120672026 100644 --- a/engine/gl/gl_draw.h +++ b/engine/gl/gl_draw.h @@ -27,6 +27,7 @@ void GLDraw_DeInit (void); void GLSurf_DeInit (void); void GLDraw_Character (int x, int y, unsigned int num); void GLDraw_ColouredCharacter (int x, int y, unsigned int num); +void GLDraw_TinyCharacter (int x, int y, unsigned int num); void GLDraw_DebugChar (qbyte num); void GLDraw_SubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height); void GLDraw_Pic (int x, int y, mpic_t *pic); diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 83562938c..78a1601f9 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -113,7 +113,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) ED_ClearEdict (progfuncs, e); if (externs->entspawn) - externs->entspawn((struct edict_s *) e); + externs->entspawn((struct edict_s *) e, false); return (struct edict_s *)e; } } @@ -133,7 +133,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) ED_ClearEdict (progfuncs, e); if (externs->entspawn) - externs->entspawn((struct edict_s *) e); + externs->entspawn((struct edict_s *) e, false); return (struct edict_s *)e; } } @@ -162,7 +162,7 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs) ED_ClearEdict (progfuncs, e); if (externs->entspawn) - externs->entspawn((struct edict_s *) e); + externs->entspawn((struct edict_s *) e, false); return (struct edict_s *)e; } @@ -1679,6 +1679,8 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) { ed = ED_AllocIntoTable(progfuncs, num); ed->isfree = true; + if (externs->entspawn) + externs->entspawn((struct edict_s *) ed, true); } } } @@ -1701,6 +1703,8 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) } } ed->isfree = false; + if (externs->entspawn) + externs->entspawn((struct edict_s *) ed, true); file = ED_ParseEdict(progfuncs, file, ed); if (killonspawnflags) @@ -1791,6 +1795,9 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) ed = ED_AllocIntoTable(progfuncs, num); ed->isfree = true; } + + if (externs->entspawn) + externs->entspawn((struct edict_s *) ed, true); } } @@ -1946,6 +1953,9 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) if (!ed) ed = ED_AllocIntoTable(progfuncs, numents); + if (externs->entspawn) + externs->entspawn((struct edict_s *) ed, true); + sv_num_edicts = numents; ed->isfree = false; file = ED_ParseEdict (progfuncs, file, ed); @@ -1976,6 +1986,8 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else ed = (edictrun_t *)ED_Alloc(progfuncs); ed->isfree = false; + if (externs->entspawn) + externs->entspawn((struct edict_s *) ed, true); file = ED_ParseEdict(progfuncs, file, ed); if (killonspawnflags) @@ -2138,6 +2150,9 @@ struct edict_s *RestoreEnt (progfuncs_t *progfuncs, char *buf, int *size, struct ent = (edictrun_t *)ed; ent->isfree = false; + if (externs->entspawn) + externs->entspawn((struct edict_s *) ent, false); + buf = ED_ParseEdict(progfuncs, buf, ent); *size = buf - start; diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 132c7c623..942d37ace 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -148,7 +148,7 @@ typedef struct progexterns_s { void (VARGS *Abort) (char *, ...); int edictsize; //size of edict_t - void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set + void (*entspawn) (struct edict_s *ent, int loading); //ent has been spawned, but may not have all the extra variables (that may need to be set) set pbool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed void (*stateop) (progfuncs_t *prinst, float var, func_t func); //what to do on qc's state opcode. void (*cstateop) (progfuncs_t *prinst, float vara, float varb, func_t currentfunc); //a hexen2 opcode. diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index ce8d01529..0a4404162 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -157,19 +157,23 @@ pbool QC_WriteFile(char *name, void *data, int len) return true; } -void ED_Spawned (struct edict_s *ent) +void ED_Spawned (struct edict_s *ent, int loading) { #ifdef VM_Q1 if (!ent->xv) ent->xv = (extentvars_t *)(ent->v+1); #endif - ent->xv->dimension_see = 255; - ent->xv->dimension_seen = 255; - ent->xv->dimension_ghost = 0; - ent->xv->dimension_solid = 255; - ent->xv->dimension_hit = 255; - ent->xv->Version = sv.csqcentversion[ent->entnum]+1; + if (!loading || !ent->xv->Version) + { + ent->xv->dimension_see = 255; + ent->xv->dimension_seen = 255; + ent->xv->dimension_ghost = 0; + ent->xv->dimension_solid = 255; + ent->xv->dimension_hit = 255; + + ent->xv->Version = sv.csqcentversion[ent->entnum]+1; + } } pbool ED_CanFree (edict_t *ed) @@ -613,25 +617,26 @@ void PR_LoadGlabalStruct(void) SV_QCStatName(ev_float, "rings_active", STAT_H2_RINGS_ACTIVE); SV_QCStatName(ev_float, "rings_low", STAT_H2_RINGS_LOW); - SV_QCStatName(ev_float, "armor_amulet", STAT_H2_AMULET); - SV_QCStatName(ev_float, "armor_bracer", STAT_H2_BRACER); - SV_QCStatName(ev_float, "armor_breastplate", STAT_H2_BREASTPLATE); - SV_QCStatName(ev_float, "armor_helmet", STAT_H2_HELMET); + SV_QCStatName(ev_float, "armor_amulet", STAT_H2_ARMOUR2); + SV_QCStatName(ev_float, "armor_bracer", STAT_H2_ARMOUR4); + SV_QCStatName(ev_float, "armor_breastplate", STAT_H2_ARMOUR3); + SV_QCStatName(ev_float, "armor_helmet", STAT_H2_ARMOUR1); SV_QCStatName(ev_float, "ring_flight", STAT_H2_FLIGHT_T); SV_QCStatName(ev_float, "ring_water", STAT_H2_WATER_T); SV_QCStatName(ev_float, "ring_turning", STAT_H2_TURNING_T); SV_QCStatName(ev_float, "ring_regeneration", STAT_H2_REGEN_T); - SV_QCStatName(ev_string, "puzzle_inv1", STAT_H2_PUZZLE1A); - SV_QCStatName(ev_string, "puzzle_inv2", STAT_H2_PUZZLE2A); - SV_QCStatName(ev_string, "puzzle_inv3", STAT_H2_PUZZLE3A); - SV_QCStatName(ev_string, "puzzle_inv4", STAT_H2_PUZZLE4A); - SV_QCStatName(ev_string, "puzzle_inv5", STAT_H2_PUZZLE5A); - SV_QCStatName(ev_string, "puzzle_inv6", STAT_H2_PUZZLE6A); - SV_QCStatName(ev_string, "puzzle_inv7", STAT_H2_PUZZLE7A); - SV_QCStatName(ev_string, "puzzle_inv8", STAT_H2_PUZZLE8A); + SV_QCStatName(ev_string, "puzzle_inv1", STAT_H2_PUZZLE1); + SV_QCStatName(ev_string, "puzzle_inv2", STAT_H2_PUZZLE2); + SV_QCStatName(ev_string, "puzzle_inv3", STAT_H2_PUZZLE3); + SV_QCStatName(ev_string, "puzzle_inv4", STAT_H2_PUZZLE4); + SV_QCStatName(ev_string, "puzzle_inv5", STAT_H2_PUZZLE5); + SV_QCStatName(ev_string, "puzzle_inv6", STAT_H2_PUZZLE6); + SV_QCStatName(ev_string, "puzzle_inv7", STAT_H2_PUZZLE7); + SV_QCStatName(ev_string, "puzzle_inv8", STAT_H2_PUZZLE8); SV_QCStatName(ev_float, "max_health", STAT_H2_MAXHEALTH); SV_QCStatName(ev_float, "max_mana", STAT_H2_MAXMANA); SV_QCStatName(ev_float, "flags", STAT_H2_FLAGS); + SV_QCStatName(ev_float, "playerclass", STAT_H2_PLAYERCLASS); } } @@ -996,7 +1001,9 @@ void Q_InitProgs(void) svs.numprogs=0; d1 = COM_FDepthFile("progs.dat", true); - d2 = COM_FDepthFile("qwprogs.dat", true) + (!deathmatch.value * 3); + d2 = COM_FDepthFile("qwprogs.dat", true); + if (d2 != 0x7fffffff) + d2 += (!deathmatch.value * 3); if (d1 < d2) //progs.dat is closer to the gamedir strcpy(addons, "progs.dat"); else if (d1 > d2) //qwprogs.dat is closest @@ -2116,13 +2123,14 @@ void PF_setmodel (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_set_puzzle_model (progfuncs_t *prinst, struct globalvars_s *pr_globals) { //qc/hc lacks string manipulation. + edict_t *e; char *shortname; char fullname[MAX_QPATH]; + e = G_EDICT(prinst, OFS_PARM0); shortname = PR_GetStringOfs(prinst, OFS_PARM1); + snprintf(fullname, sizeof(fullname)-1, "models/puzzle/%s.mdl", shortname); - G_INT(OFS_PARM1) = (int)(fullname - prinst->stringtable); - PF_setmodel (prinst, pr_globals); - G_INT(OFS_PARM1) = (int)(shortname - prinst->stringtable); //piece of mind. + PF_setmodel_Internal(prinst, e, fullname); } /* @@ -3838,9 +3846,8 @@ void PF_precache_puzzle_model (progfuncs_t *prinst, struct globalvars_s *pr_glob char fullname[MAX_QPATH]; shortname = PR_GetStringOfs(prinst, OFS_PARM0); snprintf(fullname, sizeof(fullname)-1, "models/puzzle/%s.mdl", shortname); - G_INT(OFS_PARM0) = (int)(fullname - prinst->stringtable); - PF_precache_model (prinst, pr_globals); - G_INT(OFS_PARM0) = (int)(shortname - prinst->stringtable); //piece of mind. + + PF_precache_model_Internal(prinst, fullname); } void PF_WeapIndex (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -10742,7 +10749,10 @@ void PR_RegisterFields(void) //it's just easier to do it this way. fieldxvector(colormod); - fieldxvector(color); +// if (progstype == PROG_H2) + { + fieldxvector(color); + } fieldxfloat(light_lev); fieldxfloat(style); fieldxfloat(pflags); diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 2bca729d6..fa1ff403c 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -398,7 +398,7 @@ static edict_t *Q1QVMPF_EntAlloc(progfuncs_t *pf) { Q1QVMED_ClearEdict (e, true); - ED_Spawned((struct edict_s *) e); + ED_Spawned((struct edict_s *) e, false); return (struct edict_s *)e; } } @@ -414,7 +414,7 @@ static edict_t *Q1QVMPF_EntAlloc(progfuncs_t *pf) { Q1QVMED_ClearEdict (e, true); - ED_Spawned((struct edict_s *) e); + ED_Spawned((struct edict_s *) e, false); return (struct edict_s *)e; } } @@ -431,7 +431,7 @@ static edict_t *Q1QVMPF_EntAlloc(progfuncs_t *pf) // new ents come ready wiped // Q1QVMED_ClearEdict (e, false); - ED_Spawned((struct edict_s *) e); + ED_Spawned((struct edict_s *) e, false); return (struct edict_s *)e; } diff --git a/engine/server/progs.h b/engine/server/progs.h index 78833d80d..683f4ac9f 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -32,7 +32,7 @@ void PR_LoadGlabalStruct(void); void Q_InitProgs(void); void PR_RegisterFields(void); void PR_Init(void); -void ED_Spawned (struct edict_s *ent); +void ED_Spawned (struct edict_s *ent, int loading); qboolean PR_KrimzonParseCommand(char *s); qboolean PR_UserCmd(char *cmd); qboolean PR_ConsoleCmd(void); diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 3cec270bf..df2a86fdd 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -682,6 +682,8 @@ qboolean SV_LoadLevelCache(char *level, char *startspot, qboolean ignoreplayers) svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf)); svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf)); + + svs.clients[i].playerclass = ent->xv->playerclass; } if (!ignoreplayers) diff --git a/engine/server/server.h b/engine/server/server.h index 830e4cc27..e8e910770 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1277,7 +1277,7 @@ extern cvar_t sv_demoMaxSize; extern cvar_t sv_demoMaxDirSize; void SV_MVDInit(void); -char *SV_MVDNum(int num); //filename for demonum +char *SV_MVDNum(char *buffer, int bufferlen, int num); void SV_SendMVDMessage(void); qboolean SV_ReadMVD (void); void SV_FlushDemoSignon (void); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index cd204e1a0..cf8a87d38 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -1330,6 +1330,8 @@ void SV_Status_f (void) Con_Printf ("avg response time: %i ms\n",(int)avg); Con_Printf ("packets/frame : %5.2f\n", pak); //not relevent as a limit. + Con_Printf ("current map : %s\n", sv.mapname); + // min fps lat drp if (columns < 80) { diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 0d2ce1507..e0086636f 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2011,7 +2011,7 @@ typedef struct gibfilter_s { int maxframe; } gibfilter_t; gibfilter_t *gibfilter; -void SV_GibFilterAdd(char *modelname, int min, int max) +void SV_GibFilterAdd(char *modelname, int min, int max, qboolean allowwarn) { int i; gibfilter_t *gf; @@ -2021,7 +2021,8 @@ void SV_GibFilterAdd(char *modelname, int min, int max) break; if (!sv.strings.model_precache[i]) { - Con_Printf("Filtered model \"%s\" was not precached\n", modelname); + if (allowwarn) + Con_Printf("Filtered model \"%s\" was not precached\n", modelname); return; //model not in use. } @@ -2053,10 +2054,10 @@ void SV_GibFilterInit(void) if (!file) { Con_DPrintf("gibfiltr.cfg file was not found. Using defaults\n"); - SV_GibFilterAdd("progs/gib1.mdl", -1, -1); - SV_GibFilterAdd("progs/gib2.mdl", -1, -1); - SV_GibFilterAdd("progs/gib3.mdl", -1, -1); - SV_GibFilterAdd("progs/h_player.mdl", -1, -1); + SV_GibFilterAdd("progs/gib1.mdl", -1, -1, false); + SV_GibFilterAdd("progs/gib2.mdl", -1, -1, false); + SV_GibFilterAdd("progs/gib3.mdl", -1, -1, false); + SV_GibFilterAdd("progs/h_player.mdl", -1, -1, false); return; } while(file) @@ -2075,7 +2076,7 @@ void SV_GibFilterInit(void) Con_Printf("Sudden ending to gibfiltr.cfg\n"); return; } - SV_GibFilterAdd(com_token, min, max); + SV_GibFilterAdd(com_token, min, max, true); } } qboolean SV_GibFilter(edict_t *ent) @@ -2438,7 +2439,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore continue; //not in this dimension - sorry... - if (!ignorepvs && ent != clent && (pvsflags & PVSF_MODE_MASK)==PVSF_NORMALPVS) + if (!ignorepvs && ent != clent && (pvsflags & PVSF_MODE_MASK)==PVSF_NORMALPVS && !((unsigned int)ent->v->effects & (EF_DIMLIGHT|EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_BRIGHTFIELD))) { //more expensive culling if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value) if (Cull_Traceline(clent, ent)) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 1290eb504..1574361f7 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1092,7 +1092,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us ent->v->solid = SOLID_BSP; ent->v->movetype = MOVETYPE_PUSH; - ED_Spawned(ent); + ED_Spawned(ent, false); if (progstype == PROG_QW && pr_imitatemvdsv.value>0) { diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index c27636ef6..0f175309a 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -644,25 +644,27 @@ typedef struct int size; int numfiles; int numdirs; + + int maxfiles; } dir_t; #define SORT_NO 0 #define SORT_BY_DATE 1 #ifdef _WIN32 -dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) +dir_t *Sys_listdir (char *path, char *ext, qboolean usesorting) { - static file_t list[MAX_DIRFILES]; - dir_t dir; + unsigned int maxfiles = MAX_DIRFILES; + dir_t *dir = malloc(sizeof(*dir) + sizeof(*dir->files)*maxfiles); HANDLE h; WIN32_FIND_DATA fd; int i, pos, size; char name[MAX_MVD_NAME], *s; - memset(list, 0, sizeof(list)); - memset(&dir, 0, sizeof(dir)); + memset(dir, 0, sizeof(*dir)); - dir.files = list; + dir->files = (file_t*)(dir+1); + dir->maxfiles = maxfiles; h = FindFirstFile (va("%s/*.*", path), &fd); if (h == INVALID_HANDLE_VALUE) @@ -674,13 +676,13 @@ dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) { if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - dir.numdirs++; + dir->numdirs++; continue; } size = fd.nFileSizeLow; Q_strncpyz (name, fd.cFileName, MAX_MVD_NAME); - dir.size += size; + dir->size += size; for (s = fd.cFileName + strlen(fd.cFileName); s > fd.cFileName; s--) { @@ -700,36 +702,43 @@ dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) } #endif - i = dir.numfiles; + i = dir->numfiles; pos = i; - dir.numfiles++; - for (i=dir.numfiles-1 ; i>pos ; i--) - list[i] = list[i-1]; + dir->numfiles++; + for (i=dir->numfiles-1 ; i>pos ; i--) + dir->files[i] = dir->files[i-1]; - strcpy (list[i].name, name); - list[i].size = size; - if (dir.numfiles == MAX_DIRFILES) + strcpy (dir->files[i].name, name); + dir->files[i].size = size; + if (dir->numfiles == dir->maxfiles) break; } while ( FindNextFile(h, &fd) ); FindClose (h); return dir; } + +void Sys_freedir(dir_t *dir) +{ + free(dir); +} + #else #include -dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) +dir_t *Sys_listdir (char *path, char *ext, qboolean usesorting) { - static file_t list[MAX_DIRFILES]; - dir_t d; + unsigned int maxfiles = MAX_DIRFILES; + dir_t *d = malloc(sizeof(*d) + sizeof(*d->files)*maxfiles); + int i, extsize; DIR *dir; struct dirent *oneentry; char pathname[MAX_OSPATH]; qboolean all; - memset(list, 0, sizeof(list)); - memset(&d, 0, sizeof(d)); - d.files = list; + memset(d, 0, sizeof(*d)); + d->files = (file_t*)(d+1); + d->maxfiles = maxfiles; extsize = strlen(ext); all = !strcmp(ext, ".*"); @@ -754,17 +763,17 @@ dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) #endif sprintf(pathname, "%s/%s", path, oneentry->d_name); - list[d.numfiles].size = COM_FileSize(pathname); - d.size += list[d.numfiles].size; + list[d->numfiles].size = COM_FileSize(pathname); + d->size += list[d->numfiles].size; i = strlen(oneentry->d_name); if (!all && (i < extsize || (Q_strcasecmp(oneentry->d_name+i-extsize, ext)))) continue; - Q_strncpyz(list[d.numfiles].name, oneentry->d_name, MAX_MVD_NAME); + Q_strncpyz(list[d->numfiles].name, oneentry->d_name, MAX_MVD_NAME); + d->numfiles++; - - if (++d.numfiles == MAX_DIRFILES) + if (d->numfiles == d->maxfiles) break; } @@ -772,6 +781,10 @@ dir_t Sys_listdir (char *path, char *ext, qboolean usesorting) return d; } +void Sys_freedir(dir_t *dir) +{ + free(dir); +} #endif @@ -2011,7 +2024,7 @@ void SV_MVD_Record_f (void) int c; char name[MAX_OSPATH+MAX_MVD_NAME]; char newname[MAX_MVD_NAME]; - dir_t dir; + dir_t *dir; c = Cmd_Argc(); if (c != 2) @@ -2026,11 +2039,14 @@ void SV_MVD_Record_f (void) } dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".*", SORT_NO); - if (sv_demoMaxDirSize.value && dir.size > sv_demoMaxDirSize.value*1024) + if (sv_demoMaxDirSize.value && dir->size > sv_demoMaxDirSize.value*1024) { Con_Printf("insufficient directory space, increase sv_demoMaxDirSize\n"); + Sys_freedir(dir); return; } + Sys_freedir(dir); + dir = NULL; Q_strncpyz(newname, va("%s%s", sv_demoPrefix.string, SV_CleanName(Cmd_Argv(1))), sizeof(newname) - strlen(sv_demoSuffix.string) - 5); @@ -2252,7 +2268,7 @@ int Dem_CountTeamPlayers (char *t) void SV_MVDEasyRecord_f (void) { int c; - dir_t dir; + dir_t *dir; char name[1024]; char name2[MAX_OSPATH*7]; // scream //char name2[MAX_OSPATH*2]; @@ -2273,11 +2289,13 @@ void SV_MVDEasyRecord_f (void) } dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".*", SORT_NO); - if (sv_demoMaxDirSize.value && dir.size > sv_demoMaxDirSize.value*1024) + if (sv_demoMaxDirSize.value && dir->size > sv_demoMaxDirSize.value*1024) { Con_Printf("insufficient directory space, increase sv_demoMaxDirSize\n"); + Sys_freedir(dir); return; } + Sys_freedir(dir); if (c == 2) Q_strncpyz (name, Cmd_Argv(1), sizeof(name)); @@ -2466,14 +2484,14 @@ void SV_MVDStream_Poll(void) void SV_MVDList_f (void) { mvddest_t *d; - dir_t dir; + dir_t *dir; file_t *list; float f; int i,j,show; Con_Printf("content of %s/%s/*.mvd\n", com_gamedir,sv_demoDir.string); dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".mvd", SORT_BY_DATE); - list = dir.files; + list = dir->files; if (!list->name[0]) { Con_Printf("no demos\n"); @@ -2499,37 +2517,102 @@ void SV_MVDList_f (void) } for (d = demo.dest; d; d = d->nextdest) - dir.size += d->totalsize; + dir->size += d->totalsize; - Con_Printf("\ndirectory size: %.1fMB\n",(float)dir.size/(1024*1024)); + Con_Printf("\ndirectory size: %.1fMB\n",(float)dir->size/(1024*1024)); if (sv_demoMaxDirSize.value) { - f = (sv_demoMaxDirSize.value*1024 - dir.size)/(1024*1024); + f = (sv_demoMaxDirSize.value*1024 - dir->size)/(1024*1024); if ( f < 0) f = 0; Con_Printf("space available: %.1fMB\n", f); } + + Sys_freedir(dir); } -char *SV_MVDNum(int num) +void SV_UserCmdMVDList_f (void) +{ + mvddest_t *d; + dir_t *dir; + file_t *list; + float f; + int i,j,show; + + int first; + + first = Cmd_Argv(0); + + Con_Printf("available demos\n"); + dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".mvd", SORT_BY_DATE); + list = dir->files; + if (!list->name[0]) + { + Con_Printf("no demos\n"); + } + + for (i = 1; list->name[0]; i++, list++) + { + for (j = 1; j < Cmd_Argc(); j++) + if (strstr(list->name, Cmd_Argv(j)) == NULL) + break; + show = Cmd_Argc() == j; + + if (show) + { + for (d = demo.dest; d; d = d->nextdest) + { + if (!strcmp(list->name, d->name)) + Con_Printf("*%d: %s %dk\n", i, list->name, d->totalsize/1024); + } + if (!d) + Con_Printf("%d: %s %dk\n", i, list->name, list->size/1024); + } + } + + for (d = demo.dest; d; d = d->nextdest) + dir->size += d->totalsize; + + Con_Printf("\ndirectory size: %.1fMB\n",(float)dir->size/(1024*1024)); + if (sv_demoMaxDirSize.value) + { + f = (sv_demoMaxDirSize.value*1024 - dir->size)/(1024*1024); + if ( f < 0) + f = 0; + Con_Printf("space available: %.1fMB\n", f); + } + + Sys_freedir(dir); +} + +char *SV_MVDNum(char *buffer, int bufferlen, int num) { file_t *list; - dir_t dir; + dir_t *dir; dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".mvd", SORT_BY_DATE); - list = dir.files; + list = dir->files; if (num <= 0) + { + Sys_freedir(dir); return NULL; + } num--; while (list->name[0] && num) {list++; num--;}; if (list->name[0]) + { + Q_strncpyz(buffer, list->name, bufferlen); return list->name; + } + else + buffer = NULL; - return NULL; + Sys_freedir(dir); + return buffer; } char *SV_MVDName2Txt(char *name) @@ -2549,9 +2632,9 @@ char *SV_MVDName2Txt(char *name) return va("%s", s); } -char *SV_MVDTxTNum(int num) +char *SV_MVDTxTNum(char *buffer, int bufferlen, int num) { - return SV_MVDName2Txt(SV_MVDNum(num)); + return SV_MVDName2Txt(SV_MVDNum(buffer, bufferlen, num)); } void SV_MVDRemove_f (void) @@ -2569,14 +2652,14 @@ void SV_MVDRemove_f (void) ptr = Cmd_Argv(1); if (*ptr == '*') { - dir_t dir; + dir_t *dir; file_t *list; // remove all demos with specified token ptr++; dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".mvd", SORT_BY_DATE); - list = dir.files; + list = dir->files; for (i = 0;list->name[0]; list++) { if (strstr(list->name, ptr)) @@ -2595,6 +2678,7 @@ void SV_MVDRemove_f (void) Sys_remove(SV_MVDName2Txt(path)); } } + Sys_freedir(dir); if (i) { @@ -2629,6 +2713,7 @@ void SV_MVDRemove_f (void) void SV_MVDRemoveNum_f (void) { int num; + char namebuf[MAX_QPATH]; char *val, *name; char path[MAX_OSPATH]; @@ -2645,7 +2730,7 @@ void SV_MVDRemoveNum_f (void) return; } - name = SV_MVDNum(num); + name = SV_MVDNum(namebuf, sizeof(namebuf), num); if (name != NULL) { @@ -2668,6 +2753,7 @@ void SV_MVDRemoveNum_f (void) void SV_MVDInfoAdd_f (void) { + char namebuf[MAX_QPATH]; char *name, *args, path[MAX_OSPATH]; FILE *f; @@ -2688,7 +2774,7 @@ void SV_MVDInfoAdd_f (void) } else { - name = SV_MVDTxTNum(atoi(Cmd_Argv(1))); + name = SV_MVDTxTNum(namebuf, sizeof(namebuf), atoi(Cmd_Argv(1))); if (!name) { @@ -2718,6 +2804,7 @@ void SV_MVDInfoAdd_f (void) void SV_MVDInfoRemove_f (void) { + char namebuf[MAX_QPATH]; char *name, path[MAX_OSPATH]; if (Cmd_Argc() < 2) @@ -2738,7 +2825,7 @@ void SV_MVDInfoRemove_f (void) } else { - name = SV_MVDTxTNum(atoi(Cmd_Argv(1))); + name = SV_MVDTxTNum(namebuf, sizeof(namebuf), atoi(Cmd_Argv(1))); if (!name) { @@ -2756,6 +2843,7 @@ void SV_MVDInfoRemove_f (void) void SV_MVDInfo_f (void) { + int len; char buf[64]; FILE *f = NULL; char *name, path[MAX_OSPATH]; @@ -2778,7 +2866,7 @@ void SV_MVDInfo_f (void) } else { - name = SV_MVDTxTNum(atoi(Cmd_Argv(1))); + name = SV_MVDTxTNum(buf, sizeof(buf), atoi(Cmd_Argv(1))); if (!name) { @@ -2795,9 +2883,12 @@ void SV_MVDInfo_f (void) return; } - while (!feof(f)) + for(;;) { - buf[fread (buf, 1, sizeof(buf)-1, f)] = 0; + len = fread (buf, 1, sizeof(buf)-1, f); + if (len < 0) + break; + buf[len] = 0; Con_Printf("%s", buf); } @@ -2813,6 +2904,7 @@ void SV_MVDInfo_f (void) void SV_MVDPlayNum_f(void) { + char namebuf[MAX_QPATH]; char *name; int num; char *val; @@ -2830,7 +2922,7 @@ void SV_MVDPlayNum_f(void) return; } - name = SV_MVDNum(atoi(val)); + name = SV_MVDNum(namebuf, sizeof(namebuf), atoi(val)); if (name) Cbuf_AddText(va("mvdplay %s\n", name), Cmd_ExecLevel); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 0a8224d0d..cbafdc0a3 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1377,7 +1377,7 @@ void SV_Begin_f (void) return; } - if (progstype == PROG_H2) + if (progstype == PROG_H2 && host_client->playerclass) host_client->edict->xv->playerclass = host_client->playerclass; //make sure it's set the same as the userinfo for (split = host_client; split; split = split->controlled) @@ -1939,7 +1939,8 @@ void SV_BeginDownload_f(void) // MVD hacked junk if (!strncmp(name, "demonum/", 8)) { - char *mvdname = SV_MVDNum(atoi(name+8)); + char mvdnamebuffer[MAX_QPATH]; + char *mvdname = SV_MVDNum(mvdnamebuffer, sizeof(mvdnamebuffer), atoi(name+8)); if (!mvdname) { @@ -3242,7 +3243,7 @@ void SV_SetUpClientEdict (client_t *cl, edict_t *ent) ED_ClearEdict(svprogfuncs, ent); ent->v->netname = PR_SetString(svprogfuncs, cl->name); } - ED_Spawned(ent); + ED_Spawned(ent, false); ent->isfree = false; ent->v->colormap = NUM_FOR_EDICT(svprogfuncs, ent); @@ -3773,7 +3774,7 @@ void SVNQ_Spawn_f (void) else { memset (ent->v, 0, pr_edict_size); - ED_Spawned(ent); + ED_Spawned(ent, false); ent->v->colormap = NUM_FOR_EDICT(svprogfuncs, ent); ent->v->team = 0; // FIXME diff --git a/engine/sw/sw_draw.c b/engine/sw/sw_draw.c index 8002f541d..d5b9dd151 100644 --- a/engine/sw/sw_draw.c +++ b/engine/sw/sw_draw.c @@ -653,6 +653,11 @@ void SWDraw_Character (int x, int y, unsigned int num) } } +void SWDraw_TinyCharacter (int x, int y, unsigned int num) +{ + SWDraw_Character (x, y, num); +} + /* #define drawpal(r,g,b) pal555to8[(r|(g<<5)|(b<<10)) & consolecolours[colour].rgbmask] #define draw(p) drawpal(host_basepal[p*3]>>3,host_basepal[p*3+1]>>3,host_basepal[p*3+2]>>3) diff --git a/engine/sw/sw_draw.h b/engine/sw/sw_draw.h index 5b8906fa9..df6f434fe 100644 --- a/engine/sw/sw_draw.h +++ b/engine/sw/sw_draw.h @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void SWDraw_Init (void); void SWDraw_Shutdown(void); void SWDraw_Character (int x, int y, unsigned int num); +void SWDraw_TinyCharacter (int x, int y, unsigned int num); void SWDraw_ImageColours (float r, float g, float b, float a); void SWDraw_Image (float xp, float yp, float wp, float hp, float s1, float t1, float s2, float t2, mpic_t *pic); void SWDraw_ColouredCharacter (int x, int y, unsigned int num);