void WEB_InitStartup (void) { Cmd_AddCommand("web_auth", WEB_Auth_f, "Perform the authentication against the UFOAI server"); web_username = Cvar_Get("web_username", Sys_GetCurrentUser(), CVAR_ARCHIVE, "The username for the UFOAI server."); /* if the password is a non-empty string, this means that username and password * are valid, and the authentication was successful */ web_password = Cvar_Get("web_password", "", CVAR_ARCHIVE, "The encrypted password for the UFOAI server."); web_userid = Cvar_Get("web_userid", "0", 0, "Your userid for the UFOAI server"); web_authurl = Cvar_Get("web_authurl", WEB_API_SERVER "api/auth.php", CVAR_ARCHIVE, "The url to perform the authentication against."); WEB_CGameCvars(); WEB_CGameCommands(); Com_Printf("\n------- web initialization ---------\n"); if (Q_strvalid(web_password->string)) { Com_Printf("... using username '%s'\n", web_username->string); if (!WEB_GetURL(web_authurl->string, WEB_AuthResponse)) { Cvar_Set("web_password", ""); } if (Q_strvalid(web_password->string)) { Com_Printf("... login successful\n"); } else { Com_Printf("... login failed\n"); } } else { Com_Printf("... web access not yet configured\n"); } }
/** * @note Think function */ static void LET_Projectile (le_t* le) { if (cl.time >= le->endTime) { vec3_t impact; VectorCopy(le->origin, impact); CL_ParticleFree(le->ptl); /* don't run the think function again */ le->inuse = false; if (Q_strvalid(le->ref1)) { VectorCopy(le->ptl->s, impact); le->ptl = CL_ParticleSpawn(le->ref1, 0, impact, bytedirs[le->angle]); VecToAngles(bytedirs[le->state], le->ptl->angles); } if (Q_strvalid(le->ref2)) { S_LoadAndPlaySample(le->ref2, impact, le->fd->impactAttenuation, SND_VOLUME_WEAPONS); } if (le->ref3) { /* Spawn blood particles (if defined) if actor(-body) was hit. Even if actor is dead. */ /** @todo Special particles for stun attack (mind you that there is * electrical and gas/chemical stunning)? */ if (le->fd->obj->dmgtype != csi.damStunGas) LE_ActorBodyHit(le->ref3, impact, le->angle); CL_ActorPlaySound(le->ref3, SND_HURT); } } else if (CL_OutsideMap(le->ptl->s, UNIT_SIZE * 10)) { le->endTime = cl.time; CL_ParticleFree(le->ptl); /* don't run the think function again */ le->inuse = false; } }
/** * @brief Executes console commands after a mission * * @param[in] mission Pointer to the mission to execute the triggers for * @param[in] won Int value that is one when you've won the game, and zero when the game was lost * Can execute console commands (triggers) on win and lose * This can be used for story dependent missions */ void CP_ExecuteMissionTrigger (const mission_t* mission, bool won) { Com_DPrintf(DEBUG_CLIENT, "Execute mission triggers\n"); if (mission == nullptr) return; /* we add them only here - and remove them afterwards to prevent cheating */ CP_CampaignTriggerFunctions(true); if (won) { if (Q_strvalid(mission->onwin)) { Com_DPrintf(DEBUG_CLIENT, "...won - executing '%s'\n", mission->onwin); cgi->Cmd_ExecuteString("%s", mission->onwin); } if (mission->mapDef && Q_strvalid(mission->mapDef->onwin)) { Com_DPrintf(DEBUG_CLIENT, "...won - executing '%s'\n", mission->mapDef->onwin); cgi->Cmd_ExecuteString("%s", mission->mapDef->onwin); } } else { if (Q_strvalid(mission->onlose)) { Com_DPrintf(DEBUG_CLIENT, "...lost - executing '%s'\n", mission->onlose); cgi->Cmd_ExecuteString("%s", mission->onlose); } if (mission->mapDef && Q_strvalid(mission->mapDef->onlose)) { Com_DPrintf(DEBUG_CLIENT, "...lost - executing '%s'\n", mission->mapDef->onlose); cgi->Cmd_ExecuteString("%s", mission->mapDef->onlose); } } CP_CampaignTriggerFunctions(false); }
CGAME_HARD_LINKED_FUNCTIONS static void GAME_SK_InitMissionBriefing (const char** title, linkedList_t** victoryConditionsMsgIDs, linkedList_t** missionBriefingMsgIDs) { const mapDef_t* md = cgi->GAME_GetCurrentSelectedMap(); if (Q_strvalid(md->victoryCondition)) { cgi->LIST_AddString(victoryConditionsMsgIDs, md->victoryCondition); } if (Q_strvalid(md->missionBriefing)) { cgi->LIST_AddString(missionBriefingMsgIDs, md->missionBriefing); } if (Q_strvalid(md->description)) { *title = _(md->description); } }
/** * @brief Triggers a campaign event with a special type * @param[in] type the event type * @param[in] userdata Any userdata that is passed to the bep checker function */ void CP_TriggerEvent (campaignTriggerEventType_t type, const void* userdata) { int i; for (i = 0; i < ccs.numCampaignTriggerEvents; i++) { campaignTriggerEvent_t *event = &ccs.campaignTriggerEvents[i]; if (event->type != type || (!event->active && event->reactivate == NULL)) continue; if (event->active) { if (BEP_Evaluate(event->require, CP_CheckTriggerEvent, userdata)) { if (Q_strvalid(event->command)) { CP_CampaignTriggerFunctions(true); cgi->Cbuf_AddText(event->command); cgi->Cbuf_Execute(); CP_CampaignTriggerFunctions(false); } if (event->once) { event->active = false; } } } else { event->active = BEP_Evaluate(event->reactivate, CP_CheckTriggerEvent, userdata); } } }
void M_Frame (void) { if (snd_music_play && snd_music_play->modified) { music.playing = snd_music_play->integer != 0; snd_music_play->modified = false; } if (!music.playing) { if (Mix_PlayingMusic()) M_Stop(); return; } if (snd_music->modified) { M_Start(snd_music->string); snd_music->modified = false; } if (snd_music_volume->modified) { Mix_VolumeMusic(snd_music_volume->integer); snd_music_volume->modified = false; } if (music.playingStream) { M_MusicStreamUpdate(); } else if (!Mix_PlayingMusic()) { M_Stop(); /* free the allocated memory */ if (Q_strvalid(music.nextTrack)) { M_Start(music.nextTrack); music.nextTrack[0] = '\0'; } else { if (!M_PlayRandomByCategory(music.category)) M_Start(music.currentTrack); } } }
/** * @brief Run eventhandler script for a building * @param[in] buildingTemplate Building type (template) to run event for * @param[in] base The base to run it at * @param[in] eventType Type of the event to run * @return @c true if an event was fired @c false otherwise (the building may not have one) */ bool B_FireEvent (const building_t* buildingTemplate, const base_t* base, buildingEvent_t eventType) { const char* command = nullptr; assert(buildingTemplate); assert(base); switch (eventType) { case B_ONCONSTRUCT: command = buildingTemplate->onConstruct; break; case B_ONENABLE: command = buildingTemplate->onEnable; break; case B_ONDISABLE: command = buildingTemplate->onDisable; break; case B_ONDESTROY: command = buildingTemplate->onDestroy; break; default: cgi->Com_Error(ERR_DROP, "B_FireEvent: Invalid Event\n"); } if (Q_strvalid(command)) { cgi->Cmd_ExecuteString("%s %i %i", command, base->idx, buildingTemplate->buildingType); return true; } return false; }
/** * @brief Sets the title of the installation to a cvar to prepare the rename menu. * @note it also assigns description text */ static void INS_SetInstallationTitle (installationType_t type) { const installationTemplate_t* insTemp = INS_GetInstallationTemplateByType(type); cgi->Cvar_Set("mn_installation_title", "%s #%i", (insTemp) ? _(insTemp->name) : _("Installation"), ccs.campaignStats.installationsBuilt + 1); if (!insTemp || !Q_strvalid(insTemp->description)) cgi->UI_ResetData(TEXT_BUILDING_INFO); else cgi->UI_RegisterText(TEXT_BUILDING_INFO, _(insTemp->description)); }
/** * @brief If password has changed, update sv_needpass cvar as needed */ static void CheckNeedPass (void) { if (password->modified) { password->modified = false; const int need = Q_strvalid(password->string) && Q_strcasecmp(password->string, "none") ? 1 : 0; gi.Cvar_Set("sv_needpass", "%i", need); } }
static inline void CLMN_AddBindings (keyBindSpace_t scope, char** bindings, int offset = 0) { for (int i = K_FIRST_KEY; i < K_LAST_KEY; i++) { if (Q_strnull(bindings[i])) continue; const char* binding = Cmd_GetCommandDesc(bindings[i]); if (Q_strvalid(binding)) binding = _(binding); UI_ExecuteConfunc("keybinding_add %i %i \"%s\" \"%s\"", i + offset, scope, Key_KeynumToString(i), binding); } }
/** * @brief Checks whether the given input string is allowed to be used as a user-given name string * for aircraft, soldiers, bases and so on * @param[in] input The input string to check * @return @c true if the string is valid and can be used as a name, @c false otherwise */ bool Com_IsValidName (const char* input) { /* empty strings are not allowed */ if (!Q_strvalid(input)) return false; /* names with only _ are not allowed - they would get translated with as empty msgid for gettext */ if (Q_streq(input, "_")) return false; /* there may be no quotes in the names - as they are given very often as parameter in the scripts */ if (strchr(input, '"') != nullptr) return false; return true; }
/** * @brief Adds UI Keybindings to the list for the Keylist UI * @param[in,out] list Linked list of strings to add to */ static inline void CLMN_AddUIBindings (linkedList_t **list) { int i; for (i = 0; i < UI_GetKeyBindingCount(); i++) { const uiKeyBinding_t* binding = UI_GetKeyBindingByIndex(i); if (binding == NULL) continue; if (binding->inherited) continue; if (!Q_strvalid(binding->description)) continue; LIST_AddString(list, va("%s\t%s", Key_KeynumToString(binding->key), _(binding->description))); } }
/** * @brief Adds UI Keybindings to the list for the Keylist UI */ static inline int CLMN_AddUIBindings (keyBindSpace_t scope) { int cnt = 0; const int num = UI_GetKeyBindingCount(); for (int i = 0; i < num; i++) { const uiKeyBinding_t* binding = UI_GetKeyBindingByIndex(i); if (binding == nullptr) continue; if (binding->inherited) continue; if (!Q_strvalid(binding->description)) continue; UI_ExecuteConfunc("keybinding_add %i %i \"%s\" \"%s\"", cnt++, scope, Key_KeynumToString(binding->key), _(binding->description)); } return cnt; }
/** * @brief Fills the options language menu node with the parsed language mappings * @sa CL_InitAfter * @sa CL_LocaleSet */ void CL_LanguageInit (void) { fs_i18ndir = Cvar_Get("fs_i18ndir", "", 0, "System path to language files"); char systemLanguage[MAX_VAR] = ""; if (Q_strvalid(s_language->string)) { Com_Printf("CL_LanguageInit: language settings are stored in configuration: %s\n", s_language->string); Q_strncpyz(systemLanguage, s_language->string, sizeof(systemLanguage)); } else { const char* currentLocale = Sys_GetLocale(); if (currentLocale) { const char* localeID = CL_GetLocaleID(currentLocale); if (localeID) Q_strncpyz(systemLanguage, localeID, sizeof(systemLanguage)); } } Com_DPrintf(DEBUG_CLIENT, "CL_LanguageInit: system language is: '%s'\n", systemLanguage); }
/** * @brief Performs a web auth request * @param[in] username The (unencoded) username * @param[in] password The (ununcoded) password * @note the cvars @c web_username and @c web_password are going to become overridden here. * If the auth failed, the cvar @c web_password is set to an empty string again. * @return @c true if the auth was successful, @c false otherwise. */ bool WEB_Auth (const char* username, const char* password) { char digest[41]; char user[MAX_VAR]; Q_strncpyz(user, username, sizeof(user)); Q_strlwr(user); char combined[512]; Com_sprintf(combined, sizeof(combined), "%s%s", user, password); Com_SHA1Buffer((const byte*)combined, strlen(combined), digest); Cvar_Set("web_username", "%s", username); Cvar_Set("web_password", "%s", digest); if (!WEB_GetURL(web_authurl->string, WEB_AuthResponse)) { Cvar_Set("web_password", ""); Cvar_Set("web_userid", "0"); return false; } /* if the password is still set, the auth was successful */ return Q_strvalid(web_password->string); }
static void LE_PlayFootStepSound (le_t* le) { if (Q_strvalid(le->teamDef->footstepSound)) { S_LoadAndPlaySample(le->teamDef->footstepSound, le->origin, SOUND_ATTN_NORM, SND_VOLUME_FOOTSTEPS); return; } /* walking in water will not play the normal footstep sounds */ if (!le->pathContents[le->pathPos]) { vec3_t from, to; /* prepare trace vectors */ PosToVec(le->pos, from); VectorCopy(from, to); /* we should really hit the ground with this */ to[2] -= UNIT_HEIGHT; const trace_t trace = CL_Trace(Line(from, to), AABB::EMPTY, nullptr, nullptr, MASK_SOLID, cl_worldlevel->integer); if (trace.surface) LE_PlaySoundFileAndParticleForSurface(le, trace.surface->name); } else LE_PlaySoundFileForContents(le, le->pathContents[le->pathPos]); }
/** * @brief Responses to broadcasts, etc * @sa CL_ReadPackets * @sa CL_Frame * @sa SVC_DirectConnect * @param[in,out] msg The client stream message buffer to read from */ static void CL_ConnectionlessPacket (dbuffer* msg) { char s[512]; NET_ReadStringLine(msg, s, sizeof(s)); Cmd_TokenizeString(s, false); const char* c = Cmd_Argv(0); Com_DPrintf(DEBUG_CLIENT, "server OOB: %s (%s)\n", c, Cmd_Args()); /* server connection */ if (Q_streq(c, CL_CMD_CLIENT_CONNECT)) { int i; for (i = 1; i < Cmd_Argc(); i++) { if (char const* const p = Q_strstart(Cmd_Argv(i), "dlserver=")) { Com_sprintf(cls.downloadReferer, sizeof(cls.downloadReferer), "ufo://%s", cls.servername); CL_SetHTTPServer(p); if (cls.downloadServer[0]) Com_Printf("HTTP downloading enabled, URL: %s\n", cls.downloadServer); } } if (cls.state == ca_connected) { Com_Printf("Dup connect received. Ignored.\n"); return; } dbuffer buf(5); NET_WriteByte(&buf, clc_stringcmd); NET_WriteString(&buf, NET_STATE_NEW "\n"); NET_WriteMsg(cls.netStream, buf); GAME_InitMissionBriefing(_("Loading")); return; } /* remote command from gui front end */ if (Q_streq(c, CL_CMD_COMMAND)) { if (!NET_StreamIsLoopback(cls.netStream)) { Com_Printf("Command packet from remote host. Ignored.\n"); return; } else { char str[512]; NET_ReadString(msg, str, sizeof(str)); Cbuf_AddText("%s\n", str); } return; } /* ping from server */ if (Q_streq(c, CL_CMD_PING)) { NET_OOB_Printf(cls.netStream, SV_CMD_ACK); return; } /* echo request from server */ if (Q_streq(c, CL_CMD_ECHO)) { NET_OOB_Printf(cls.netStream, "%s", Cmd_Argv(1)); return; } /* print */ if (Q_streq(c, SV_CMD_PRINT)) { NET_ReadString(msg, popupText, sizeof(popupText)); /* special reject messages needs proper handling */ if (strstr(popupText, REJ_PASSWORD_REQUIRED_OR_INCORRECT)) { UI_PushWindow("serverpassword"); if (Q_strvalid(Cvar_GetString("password"))) { Cvar_Set("password", ""); CL_Drop(); UI_Popup(_("Connection failure"), _("The password you specified was wrong.")); } else { CL_Drop(); UI_Popup(_("Connection failure"), _("This server requires a password.")); } } else if (strstr(popupText, REJ_SERVER_FULL)) { CL_Drop(); UI_Popup(_("Connection failure"), _("This server is full.")); } else if (strstr(popupText, REJ_BANNED)) { CL_Drop(); UI_Popup(_("Connection failure"), _("You are banned on this server.")); } else if (strstr(popupText, REJ_GAME_ALREADY_STARTED)) { CL_Drop(); UI_Popup(_("Connection failure"), _("The game has already started.")); } else if (strstr(popupText, REJ_SERVER_VERSION_MISMATCH)) { CL_Drop(); UI_Popup(_("Connection failure"), _("The server is running a different version of the game.")); } else if (strstr(popupText, BAD_RCON_PASSWORD)) { Cvar_Set("rcon_password", ""); UI_Popup(_("Bad rcon password"), _("The rcon password you specified was wrong.")); } else if (strstr(popupText, REJ_CONNECTION_REFUSED)) { CL_Drop(); UI_Popup(_("Connection failure"), _("The server refused the connection.")); } else if (Q_strvalid(popupText)) { UI_Popup(_("Notice"), _(popupText)); } return; } if (!GAME_HandleServerCommand(c, msg)) Com_Printf("Unknown command received \"%s\"\n", c); }
/** * @brief Change the server to a new map, taking all connected clients along with it. * @note the full syntax is: @code map [day|night] [+]<map> [<assembly>] @endcode * @sa SV_AssembleMap * @sa CM_LoadMap * @sa Com_SetServerState */ void SV_Map (bool day, const char* levelstring, const char* assembly) { int i; unsigned checksum = 0; char* map = SV_GetConfigString(CS_TILES); char* pos = SV_GetConfigString(CS_POSITIONS); char* entityString = SV_GetConfigString(CS_ENTITYSTRING); MapInfo* randomMap = nullptr; client_t* cl; /* any partially connected client will be restarted */ Com_SetServerState(ss_restart); /* the game is just starting */ SV_InitGame(); if (!svs.initialized) { Com_Printf("Could not spawn the server\n"); return; } assert(Q_strvalid(levelstring)); Com_DPrintf(DEBUG_SERVER, "SpawnServer: %s\n", levelstring); /* save name for levels that don't set message */ SV_SetConfigString(CS_NAME, levelstring); SV_SetConfigString(CS_LIGHTMAP, day); SV_SetConfigString(CS_MAPZONE, Cvar_GetString("sv_mapzone")); Q_strncpyz(sv->name, levelstring, sizeof(sv->name)); /* set serverinfo variable */ sv_mapname = Cvar_FullSet("sv_mapname", sv->name, CVAR_SERVERINFO | CVAR_NOSET); /* notify the client in case of a listening server */ SCR_BeginLoadingPlaque(); if (assembly) Q_strncpyz(sv->assembly, assembly, sizeof(sv->assembly)); else sv->assembly[0] = '\0'; /* leave slots at start for clients only */ cl = nullptr; while ((cl = SV_GetNextClient(cl)) != nullptr) { /* needs to reconnect */ if (cl->state >= cs_spawning) SV_SetClientState(cl, cs_connected); } /* assemble and load the map */ if (levelstring[0] == '+') { randomMap = SV_AssembleMap(levelstring + 1, assembly, map, pos, entityString, 0, true); if (!randomMap) { Com_Printf("Could not load assembly for map '%s'\n", levelstring); return; } } else { SV_SetConfigString(CS_TILES, levelstring); SV_SetConfigString(CS_POSITIONS, assembly ? assembly : ""); SV_SetConfigString(CS_ENTITYSTRING, ""); } CM_LoadMap(map, day, pos, entityString, &sv->mapData, &sv->mapTiles); Com_Printf("checksum for the map '%s': %u\n", levelstring, sv->mapData.mapChecksum); SV_SetConfigString(CS_MAPCHECKSUM, sv->mapData.mapChecksum); checksum = Com_GetScriptChecksum(); Com_Printf("ufo script checksum %u\n", checksum); SV_SetConfigString(CS_UFOCHECKSUM, checksum); SV_SetConfigString(CS_OBJECTAMOUNT, csi.numODs); SV_SetConfigString(CS_VERSION, UFO_VERSION); SV_SetConfigString(CS_MAPTITLE, SV_GetMapTitle(randomMap, levelstring)); if (Q_strstart(SV_GetConfigString(CS_MAPTITLE), "b/")) { /* For base attack, CS_MAPTITLE contains too many chars */ SV_SetConfigString(CS_MAPTITLE, "Base attack"); SV_SetConfigString(CS_NAME, ".baseattack"); } /* clear random-map assembly data */ Mem_Free(randomMap); randomMap = nullptr; /* clear physics interaction links */ SV_ClearWorld(); /* fix this! */ for (i = 1; i <= sv->mapData.numInline; i++) sv->models[i] = CM_InlineModel(&sv->mapTiles, va("*%i", i)); /* precache and static commands can be issued during map initialization */ Com_SetServerState(ss_loading); /* load and spawn all other entities */ { const ScopedMutex scopedMutex(svs.serverMutex); svs.ge->SpawnEntities(sv->name, SV_GetConfigStringInteger(CS_LIGHTMAP), sv->mapData.mapEntityString); } /* all precaches are complete */ Com_SetServerState(ss_game); Com_Printf("-------------------------------------\n"); Cbuf_CopyToDefer(); }