X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=qcsrc%2Fclient%2FMain.qc;h=8facbf500ff9a8e2b28567b7b96bd85c88c85ebf;hb=7072a9dc696dc5bd2a5a2c4c706c4a2f5c0a24c5;hp=cf696a3228cf2d7b646601b95384442d446e3d95;hpb=2b2f4843f735c217616212640a58e88f5dc2a5f0;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index cf696a322..29ff3d52c 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -2,6 +2,19 @@ // BEGIN REQUIRED CSQC FUNCTIONS //include "main.qh" +entity clearentity_ent; +void clearentity(entity e) +{ + if not(clearentity_ent) + { + clearentity_ent = spawn(); + clearentity_ent.classname = "clearentity"; + } + float n = e.entnum; + copyentity(clearentity_ent, e); + e.entnum = n; +} + #define DP_CSQC_ENTITY_REMOVE_IS_B0RKED void menu_show_error() { @@ -19,13 +32,61 @@ void menu_sub_null() float __engine_check; #endif +void precache_playermodel(string m) +{ + string f; + + if(substring(m, -9,5) == "_lod1") + return; + if(substring(m, -9,5) == "_lod2") + return; + precache_model(m); + f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); + f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1)); + if(fexists(f)) + precache_model(f); + + /* + float globhandle, i, n; + globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE); + if (globhandle < 0) + return; + n = search_getsize(globhandle); + for (i = 0; i < n; ++i) + { + //print(search_getfilename(globhandle, i), "\n"); + f = search_getfilename(globhandle, i); + PrecachePlayerSounds(f); + } + search_end(globhandle); + */ +} +void precache_all_playermodels(string pattern) +{ + float globhandle, i, n; + string f; + + globhandle = search_begin(pattern, TRUE, FALSE); + if (globhandle < 0) + return; + n = search_getsize(globhandle); + for (i = 0; i < n; ++i) + { + //print(search_getfilename(globhandle, i), "\n"); + f = search_getfilename(globhandle, i); + precache_playermodel(f); + } + search_end(globhandle); +} + string forcefog; void WaypointSprite_Load(); void ConsoleCommand_macro_init(); void CSQC_Init(void) { prvm_language = cvar_string("prvm_language"); - #ifdef USE_FTE #pragma target ID __engine_check = checkextension("DP_SV_WRITEPICTURE"); @@ -41,20 +102,25 @@ void CSQC_Init(void) check_unacceptable_compiler_bugs(); #ifdef WATERMARK - print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK())); + print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK)); #endif float i; +#ifdef COMPAT_XON050_ENGINE + // old engine lacks implementation of player_localnum + player_localnum = player_localentnum - 1; +#endif + binddb = db_create(); tempdb = db_create(); ClientProgsDB = db_load("client.db"); compressShortVector_init(); - drawfont = FONT_USER+1; + draw_endBoldFont(); menu_visible = FALSE; menu_show = menu_show_error; - menu_action = menu_sub_null; + menu_action = func_null; for(i = 0; i < 255; ++i) if(getplayerkeyvalue(i, "viewentity") == "") @@ -83,16 +149,29 @@ void CSQC_Init(void) teams = Sort_Spawn(); players = Sort_Spawn(); - GetTeam(COLOR_SPECTATOR, true); // add specs first - - RegisterWeapons(); + GetTeam(FL_SPECTATOR, true); // add specs first + // needs to be done so early because of the constants they create + CALL_ACCUMULATED_FUNCTION(RegisterWeapons); + CALL_ACCUMULATED_FUNCTION(RegisterGametypes); + CALL_ACCUMULATED_FUNCTION(RegisterNotifications); + CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes); + WaypointSprite_Load(); // precaches precache_model("null"); precache_sound("misc/hit.wav"); precache_sound("misc/typehit.wav"); + if (autocvar_cl_precacheplayermodels) + { + precache_all_playermodels("models/player/*.zym"); + precache_all_playermodels("models/player/*.dpm"); + precache_all_playermodels("models/player/*.md3"); + precache_all_playermodels("models/player/*.psk"); + precache_all_playermodels("models/player/*.iqm"); + } + Projectile_Precache(); Hook_Precache(); GibSplash_Precache(); @@ -100,8 +179,9 @@ void CSQC_Init(void) DamageInfo_Precache(); Vehicles_Precache(); turrets_precache(); - Announcer_Precache(); + Announcer_Precache(); Tuba_Precache(); + CSQCPlayer_Precache(); if(autocvar_cl_reticle) { @@ -131,11 +211,12 @@ void CSQC_Init(void) hud_configure_prev = -1; tab_panel = -1; + + draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin"))); } // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc) -float cvar_clientsettemp_restore(); -void CSQC_Shutdown(void) +void Shutdown(void) { #ifdef USE_FTE #pragma TARGET id @@ -156,8 +237,6 @@ void CSQC_Shutdown(void) db_save(ClientProgsDB, "client.db"); db_close(ClientProgsDB); - cvar_clientsettemp_restore(); - if(camera_active) cvar_set("chase_active",ftos(chase_active_backup)); @@ -183,16 +262,16 @@ float SetTeam(entity o, float Team) switch(Team) { case -1: - case COLOR_TEAM1: - case COLOR_TEAM2: - case COLOR_TEAM3: - case COLOR_TEAM4: + case FL_TEAM_1: + case FL_TEAM_2: + case FL_TEAM_3: + case FL_TEAM_4: break; default: if(GetTeam(Team, false) == world) { print(sprintf(_("trying to switch to unsupported team %d\n"), Team)); - Team = COLOR_SPECTATOR; + Team = FL_SPECTATOR; } break; } @@ -208,7 +287,7 @@ float SetTeam(entity o, float Team) if(GetTeam(Team, false) == world) { print(sprintf(_("trying to switch to unsupported team %d\n"), Team)); - Team = COLOR_SPECTATOR; + Team = FL_SPECTATOR; } break; } @@ -307,9 +386,10 @@ float button_zoom; // CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client. // Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine. // All keys are in ascii. -// bInputType = 0 is key pressed, 1 is key released, 2 is mouse input. +// bInputType = 0 is key pressed, 1 is key released, 2 and 3 are mouse input. // In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0. // In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta. +// In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos. float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) { float bSkipKey; @@ -321,7 +401,7 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary) if (MapVote_InputEvent(bInputType, nPrimary, nSecondary)) return true; - if(menu_visible) + if(menu_visible && menu_action) if(menu_action(bInputType, nPrimary, nSecondary)) return TRUE; @@ -483,7 +563,7 @@ void Ent_ClientData() if(f & 2) { newspectatee_status = ReadByte(); - if(newspectatee_status == player_localentnum) + if(newspectatee_status == player_localnum + 1) newspectatee_status = -1; // observing } else @@ -517,6 +597,8 @@ void Ent_ClientData() prev_health = -1; } spectatee_status = newspectatee_status; + + // non-COMPAT_XON050_ENGINE: we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum } void Ent_Nagger() @@ -593,7 +675,7 @@ void Ent_ReadAccuracy(void) return; } - for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w, f *= 2) + for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) { if(sf & f) { @@ -605,6 +687,10 @@ void Ent_ReadAccuracy(void) else weapon_accuracy[w] = (b - 1.0) / 100.0; } + if(f == 0x800000) + f = 1; + else + f *= 2; } } @@ -619,6 +705,9 @@ void CSQC_Ent_Update(float bIsNewEntity) float savetime; t = ReadByte(); + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t)); + // set up the "time" global for received entities to be correct for interpolation purposes savetime = time; if(servertime) @@ -640,6 +729,7 @@ void CSQC_Ent_Update(float bIsNewEntity) //print(_("A CSQC entity changed its type!\n")); print(sprintf(_("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n"), num_for_edict(self), self.entnum, self.enttype, t)); Ent_Remove(); + clearentity(self); bIsNewEntity = 1; } } @@ -686,6 +776,9 @@ void CSQC_Ent_Update(float bIsNewEntity) case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break; case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break; case ENT_CLIENT_TURRET: ent_turret(); break; + case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break; + case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break; + case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break; default: //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype)); error(sprintf(_("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n"), self.enttype, num_for_edict(self), self.classname)); @@ -702,6 +795,18 @@ void Ent_Remove() if(self.entremove) self.entremove(); + if(self.skeletonindex) + { + skel_delete(self.skeletonindex); + self.skeletonindex = 0; + } + + if(self.snd_looping > 0) + { + sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation); + self.snd_looping = 0; + } + self.enttype = 0; self.classname = ""; self.draw = menu_sub_null; @@ -711,6 +816,14 @@ void Ent_Remove() // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well. void CSQC_Ent_Remove() { + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype)); + + if(wasfreed(self)) + { + print("WARNING: CSQC_Ent_Remove called for already removed entity. Packet loss?\n"); + return; + } if(self.enttype) Ent_Remove(); remove(self); @@ -720,24 +833,34 @@ void Gamemode_Init() { if not(isdemo()) { - localcmd("\n_cl_hook_gamestart ", GametypeNameFromType(gametype), "\n"); + if(!(calledhooks & HOOK_START)) + localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n"); calledhooks |= HOOK_START; } } // CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string. void CSQC_Parse_StuffCmd(string strMessage) { + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage)); + localcmd(strMessage); } // CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string. void CSQC_Parse_Print(string strMessage) { + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Parse_Print(\"%s\")\n", strMessage)); + print(ColorTranslateRGB(strMessage)); } // CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided. void CSQC_Parse_CenterPrint(string strMessage) { + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage)); + centerprint_hud(strMessage); } @@ -756,7 +879,7 @@ void Ent_ScoresInfo() { float i; self.classname = "ent_client_scores_info"; - gametype = ReadByte(); + gametype = ReadInt24_t(); for(i = 0; i < MAX_SCORE; ++i) { scores_label[i] = strzone(ReadString()); @@ -813,6 +936,7 @@ void Ent_Init() hagar_maxrockets = ReadByte(); g_trueaim_minrange = ReadCoord(); + g_balance_porto_secondary = ReadByte(); if(!postinit) PostInit(); @@ -963,7 +1087,7 @@ void Net_ReadRace() strunzone(grecordholder[pos-1]); grecordholder[pos-1] = strzone(ReadString()); grecordtime[pos-1] = ReadInt24_t(); - if(grecordholder[pos-1] == GetPlayerName(player_localentnum -1)) + if(grecordholder[pos-1] == GetPlayerName(player_localnum)) race_myrank = pos; break; case RACE_NET_SERVER_STATUS: @@ -1023,6 +1147,9 @@ float CSQC_Parse_TempEntity() float nTEID; nTEID = ReadByte(); + if(autocvar_developer_csqcentities) + print(sprintf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID)); + // NOTE: Could just do return instead of break... switch(nTEID) { @@ -1093,6 +1220,14 @@ float CSQC_Parse_TempEntity() Net_VehicleSetup(); bHandled = true; break; + case TE_CSQC_SVNOTICE: + cl_notice_read(); + bHandled = true; + break; + case TE_CSQC_NOTIFICATION: + Read_Notification(); + bHandled = true; + break; default: // No special logic for this temporary entity; return 0 so the engine can handle it bHandled = false; @@ -1105,13 +1240,13 @@ float CSQC_Parse_TempEntity() string getcommandkey(string text, string command) { string keys; - float n, j, k, l; + float n, j, k, l = 0; if (!autocvar_hud_showbinds) return text; keys = db_get(binddb, command); - if (!keys) + if (keys == "") { n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings for(j = 0; j < n; ++j) @@ -1129,10 +1264,12 @@ string getcommandkey(string text, string command) } } + if (keys == "") + keys = "NO_KEY"; db_put(binddb, command, keys); } - if ("" == keys) { + if (keys == "NO_KEY") { if (autocvar_hud_showbinds > 1) return sprintf(_("%s (not bound)"), text); else