void medic_idle (edict_t *self) { if(!(self->spawnflags & SF_MONSTER_AMBUSH)) gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0); if(self->monsterinfo.aiflags & AI_MEDIC) { // Then we must have reached this point after losing sight // of our patient. abortHeal(self,false); } if(medic_FindDeadMonster(self)) return; // If the map has hint_paths, AND the medic isn't at a HOLD point_combat, // AND the medic has previously called FoundTarget (trail_time set to // level.time), then look for hint_path chain and follow it, hopefully // to find monsters to resurrect if(self->monsterinfo.aiflags & AI_HINT_TEST) return; if (hint_chains_exist && !(self->monsterinfo.aiflags & AI_STAND_GROUND) && ((self->monsterinfo.trail_time > 0) || medic_test) ) { edict_t *e; edict_t *hint=NULL; float dist; vec3_t dir; int i; float bestdistance=99999; for(i=game.maxclients+1; i<globals.num_edicts; i++) { e = &g_edicts[i]; if(!e->inuse) continue; if(Q_strcasecmp(e->classname,"hint_path")) continue; if(!visible(self,e)) continue; if(!canReach(self,e)) continue; VectorSubtract(e->s.origin,self->s.origin,dir); dist = VectorLength(dir); if(dist < bestdistance) { hint = e; bestdistance = dist; } } if(hint) { self->hint_chain_id = hint->hint_chain_id; if(!self->monsterinfo.pathdir) self->monsterinfo.pathdir = 1; VectorSubtract(hint->s.origin, self->s.origin, dir); self->ideal_yaw = vectoyaw(dir); self->goalentity = self->movetarget = hint; self->monsterinfo.pausetime = 0; self->monsterinfo.aiflags |= AI_MEDIC_PATROL; self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); // run for it self->monsterinfo.run (self); } } }
// Argh! - loads id baseq2/player models, "patches" their skin links // for misc_actor (all id skins, and slots for 10 custom // skins), and saves them to the current moddir location // int PatchPlayerModels (char *modelname) { cvar_t *game; int j; int numskins; // number of skin entries char skins[MAX_MD2SKINS][MAX_SKINNAME]; // skin entries char infilename[MAX_OSPATH]; char outfilename[MAX_OSPATH]; FILE *infile; FILE *outfile; dmdl_t model; // model header byte *data; // model data int datasize; // model data size (bytes) int newoffset; // model data offset (after skins) // get game (moddir) name game = gi.cvar("game", "", 0); if (!*game->string) return 0; // we're in baseq2 sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname); if ((outfile = fopen (outfilename, "rb"))) { // output file already exists, move along fclose (outfile); // gi.dprintf ("PatchPlayerModels: Could not save %s, file already exists\n", outfilename); return 0; } // clear skin names (just in case) for (j = 0; j < MAX_MD2SKINS; j++) memset (skins[j], 0, MAX_SKINNAME); // set model-specific data if(!Q_strcasecmp(modelname,"male")) { numskins = 15; sprintf (skins[0], "players/male/cipher.pcx"); sprintf (skins[1], "players/male/claymore.pcx"); sprintf (skins[2], "players/male/flak.pcx"); sprintf (skins[3], "players/male/grunt.pcx"); sprintf (skins[4], "players/male/howitzer.pcx"); sprintf (skins[5], "players/male/major.pcx"); sprintf (skins[6], "players/male/nightops.pcx"); sprintf (skins[7], "players/male/pointman.pcx"); sprintf (skins[8], "players/male/psycho.pcx"); sprintf (skins[9], "players/male/rampage.pcx"); sprintf (skins[10], "players/male/razor.pcx"); sprintf (skins[11], "players/male/recon.pcx"); sprintf (skins[12], "players/male/scout.pcx"); sprintf (skins[13], "players/male/sniper.pcx"); sprintf (skins[14], "players/male/viper.pcx"); } else if(!Q_strcasecmp(modelname,"female")) { numskins = 10; sprintf (skins[0], "players/female/athena.pcx"); sprintf (skins[1], "players/female/brianna.pcx"); sprintf (skins[2], "players/female/cobalt.pcx"); sprintf (skins[3], "players/female/ensign.pcx"); sprintf (skins[4], "players/female/jezebel.pcx"); sprintf (skins[5], "players/female/jungle.pcx"); sprintf (skins[6], "players/female/lotus.pcx"); sprintf (skins[7], "players/female/stiletto.pcx"); sprintf (skins[8], "players/female/venus.pcx"); sprintf (skins[9], "players/female/voodoo.pcx"); } else if(!Q_strcasecmp(modelname,"cyborg")) { numskins = 3; sprintf (skins[0], "players/cyborg/oni911.pcx"); sprintf (skins[1], "players/cyborg/ps9000.pcx"); sprintf (skins[2], "players/cyborg/tyr574.pcx"); } else return 0; // fill in 32 slots with "customXX" for(j=numskins; j<32; j++) sprintf( skins[j], "players/%s/custom%d.pcx", modelname, j-numskins+1); numskins = 32; // load original player model sprintf (infilename, "baseq2/players/%s/tris.md2", modelname); if ( !(infile = fopen (infilename, "rb")) ) return 0; // no player model (this shouldn't happen) fread (&model, sizeof (dmdl_t), 1, infile); datasize = model.ofs_end - model.ofs_skins; if ( !(data = (byte*)G_Malloc (datasize)) ) // make sure freed locally { gi.dprintf ("PatchPlayerModels: Could not allocate memory for model\n"); return 0; } fread (data, sizeof (byte), datasize, infile); fclose (infile); // update model info model.num_skins = numskins; newoffset = numskins * MAX_SKINNAME; model.ofs_st += newoffset; model.ofs_tris += newoffset; model.ofs_frames += newoffset; model.ofs_glcmds += newoffset; model.ofs_end += newoffset; // save new player model sprintf (outfilename, "%s/players", game->string); // make some dirs if needed _mkdir (outfilename); sprintf (outfilename, "%s/players/%s", game->string, modelname); _mkdir (outfilename); sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname); if ( !(outfile = fopen (outfilename, "wb")) ) { // file couldn't be created for some other reason gi.dprintf ("PatchPlayerModels: Could not save %s\n", outfilename); G_Free(data); return 0; } fwrite (&model, sizeof (dmdl_t), 1, outfile); fwrite (skins, sizeof (char), newoffset, outfile); fwrite (data, sizeof (byte), datasize, outfile); fclose (outfile); gi.dprintf ("PatchPlayerModels: Saved %s\n", outfilename); G_Free(data); return 1; }
static void CD_f (void) { char *command; int ret; int n; if (Cmd_Argc() < 2) { Con_Printf("CD parameters:\n on\n off\n reset\n remap\n eject\n close\n play\n loop\n pause\n resume\n stop\n info\n"); // Manoel Kasimier return; } command = Cmd_Argv (1); if (Q_strcasecmp(command, "on") == 0) { Cvar_SetValue("cd_enabled", 1); // Manoel Kasimier - CD player in menu return; } if (Q_strcasecmp(command, "off") == 0) { if (playing) CDAudio_Stop(); Cvar_SetValue("cd_enabled", 0); // Manoel Kasimier - CD player in menu return; } if (Q_strcasecmp(command, "reset") == 0) { /* // Manoel Kasimier - Windows XP fix if (playing) CDAudio_Stop(); for (n = 0; n < 100; n++) remap[n] = n; CDAudio_GetAudioDiskInfo(); */ // Manoel Kasimier - Windows XP fix - begin CDAudio_Shutdown(); CDAudio_Init(); // Manoel Kasimier - Windows XP fix - end return; } if (Q_strcasecmp(command, "remap") == 0) { ret = Cmd_Argc() - 2; if (ret <= 0) { for (n = 1; n < 100; n++) if (remap[n] != n) Con_Printf(" %u -> %u\n", n, remap[n]); return; } for (n = 1; n <= ret; n++) remap[n] = Q_atoi(Cmd_Argv (n+1)); return; } // Manoel Kasimier - moved the "eject" command here so empty drives can be ejected if (Q_strcasecmp(command, "eject") == 0) { if (playing) CDAudio_Stop(); CDAudio_Eject(); cdValid = false; maxTrack = 0; // Manoel Kasimier - CD player in menu return; } if (Q_strcasecmp(command, "close") == 0) { CDAudio_CloseDoor(); Cbuf_AddText ("wait;cd reset\n", "cd reset"); // Manoel Kasimier - CD player in menu - auto-update CD status after closing drive door return; } if (Q_strcasecmp(command, "info") == 0) { // Manoel Kasimier - begin if (!maxTrack) Con_Printf("No CD in player.\n"); else { Con_Printf("%u tracks\n", maxTrack); if (!cdValid) Con_Printf("No audio tracks on disc\n"); else // List valid tracks { Con_Printf("Audio tracks on disc:\n"); for (n=1; n<=99; n++) if (audioTrack[n]) { if (!audioTrack[n+1]) // end of sequence, or isolated track Con_Printf(" %2i\n", n); else if (!audioTrack[n-1]) // beginning of sequence Con_Printf(" %2i -", n); } if (cd_enabled.value) { // Manoel Kasimier - end if (playing) Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); else if (wasPlaying) Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); // Manoel Kasimier - begin } } } if (!cd_enabled.value) Con_Printf("CD audio is off\n"); // Manoel Kasimier - end Con_Printf("Volume is %.1f\n", cdvolume); // Manoel Kasimier - edited return; } if (!cdValid) { CDAudio_GetAudioDiskInfo(); if (!cdValid) { // Manoel Kasimier - begin if (maxTrack) Con_Printf("No audio tracks on disc\n"); else // Manoel Kasimier - end Con_Printf("No CD in player.\n"); return; } } if (Q_strcasecmp(command, "play") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); return; } if (Q_strcasecmp(command, "loop") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); return; } if (Q_strcasecmp(command, "stop") == 0) { CDAudio_Stop(); return; } if (Q_strcasecmp(command, "pause") == 0) { CDAudio_Pause(); return; } if (Q_strcasecmp(command, "resume") == 0) { CDAudio_Resume(); return; } Con_Printf("CD parameters:\n on\n off\n reset\n remap\n eject\n close\n play\n loop\n pause\n resume\n stop\n info\n"); // Manoel Kasimier - absent/unrecognized parameter }
/* ==================== CL_UpdateLevelHunkUsage This updates the "hunkusage.dat" file with the current map and it's hunk usage count This is used for level loading, so we can show a percentage bar dependant on the amount of hunk memory allocated so far This will be slightly inaccurate if some settings like sound quality are changed, but these things should only account for a small variation (hopefully) ==================== */ void CL_UpdateLevelHunkUsage( void ) { int handle; char *memlistfile = "hunkusage.dat"; char *buf, *outbuf; char *buftrav, *outbuftrav; char *token; char outstr[256]; int len, memusage; memusage = Cvar_VariableIntegerValue( "com_hunkused" ) + Cvar_VariableIntegerValue( "hunk_soundadjust" ); len = FS_FOpenFileByMode( memlistfile, &handle, FS_READ ); if ( len >= 0 ) { // the file exists, so read it in, strip out the current entry for this map, and save it out, so we can append the new value buf = (char *)Z_Malloc( len + 1 ); memset( buf, 0, len + 1 ); outbuf = (char *)Z_Malloc( len + 1 ); memset( outbuf, 0, len + 1 ); FS_Read( (void *)buf, len, handle ); FS_FCloseFile( handle ); // now parse the file, filtering out the current map buftrav = buf; outbuftrav = outbuf; outbuftrav[0] = '\0'; while ( ( token = COM_Parse( &buftrav ) ) && token[0] ) { if ( !Q_strcasecmp( token, cl.mapname ) ) { // found a match token = COM_Parse( &buftrav ); // read the size if ( token && token[0] ) { if ( atoi( token ) == memusage ) { // if it is the same, abort this process Z_Free( buf ); Z_Free( outbuf ); return; } } } else { // send it to the outbuf Q_strcat( outbuftrav, len + 1, token ); Q_strcat( outbuftrav, len + 1, " " ); token = COM_Parse( &buftrav ); // read the size if ( token && token[0] ) { Q_strcat( outbuftrav, len + 1, token ); Q_strcat( outbuftrav, len + 1, "\n" ); } else { Com_Error( ERR_DROP, "hunkusage.dat file is corrupt\n" ); } } } #ifdef __MACOS__ //DAJ MacOS file typing { extern _MSL_IMP_EXP_C long _fcreator, _ftype; _ftype = 'TEXT'; _fcreator = 'WlfS'; } #endif handle = FS_FOpenFileWrite( memlistfile ); if ( handle < 0 ) { Com_Error( ERR_DROP, "cannot create %s\n", memlistfile ); } // input file is parsed, now output to the new file len = strlen( outbuf ); if ( FS_Write( (void *)outbuf, len, handle ) != len ) { Com_Error( ERR_DROP, "cannot write to %s\n", memlistfile ); } FS_FCloseFile( handle ); Z_Free( buf ); Z_Free( outbuf ); } // now append the current map to the current file FS_FOpenFileByMode( memlistfile, &handle, FS_APPEND ); if ( handle < 0 ) { Com_Error( ERR_DROP, "cannot write to hunkusage.dat, check disk full\n" ); } Com_sprintf( outstr, sizeof( outstr ), "%s %i\n", cl.mapname, memusage ); FS_Write( outstr, strlen( outstr ), handle ); FS_FCloseFile( handle ); // now just open it and close it, so it gets copied to the pak dir len = FS_FOpenFileByMode( memlistfile, &handle, FS_READ ); if ( len >= 0 ) { FS_FCloseFile( handle ); } }
static void _Datagram_SearchForHosts(qboolean xmit) { int ret; int n; int i; struct qsockaddr readaddr; struct qsockaddr myaddr; int control; dfunc.GetSocketAddr(dfunc.controlSock, &myaddr); if (xmit) { SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); MSG_WriteString(&net_message, "QUAKE"); MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize); SZ_Clear(&net_message); } while ((ret = dfunc.Read(dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) { if (ret < sizeof(int)) { continue; } net_message.cursize = ret; // don't answer our own query if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0) { continue; } // is the cache full? if (hostCacheCount == HOSTCACHESIZE) { continue; } MSG_BeginReading(); control = BigLong(*((int *)net_message.data)); MSG_ReadLong(); if (control == -1) { continue; } if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) { continue; } if ((control & NETFLAG_LENGTH_MASK) != ret) { continue; } if (MSG_ReadByte() != CCREP_SERVER_INFO) { continue; } dfunc.GetAddrFromName(MSG_ReadString(), &readaddr); // search the cache for this server for (n = 0; n < hostCacheCount; n++) if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0) { break; } // is it already there? if (n < hostCacheCount) { continue; } // add it hostCacheCount++; Q_strcpy(hostcache[n].name, MSG_ReadString()); Q_strcpy(hostcache[n].map, MSG_ReadString()); hostcache[n].users = MSG_ReadByte(); hostcache[n].maxusers = MSG_ReadByte(); if (MSG_ReadByte() != NET_PROTOCOL_VERSION) { Q_strcpy(hostcache[n].cname, hostcache[n].name); hostcache[n].cname[14] = 0; Q_strcpy(hostcache[n].name, "*"); Q_strcat(hostcache[n].name, hostcache[n].cname); } Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr)); hostcache[n].driver = net_driverlevel; hostcache[n].ldriver = net_landriverlevel; Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr)); // check for a name conflict for (i = 0; i < hostCacheCount; i++) { if (i == n) { continue; } if (Q_strcasecmp(hostcache[n].name, hostcache[i].name) == 0) { i = Q_strlen(hostcache[n].name); if (i < 15 && hostcache[n].name[i-1] > '8') { hostcache[n].name[i] = '0'; hostcache[n].name[i+1] = 0; } else { hostcache[n].name[i-1]++; } i = -1; } } } }
/* =============== CG_SoundParseSounds =============== */ static void CG_SoundParseSounds ( char *filename, char *buffer ) { char *token, **text; int s; long hash; soundScript_t sound; // the current sound being read soundScriptSound_t *scriptSound; qboolean inSound, wantSoundName; s = 0; inSound = qfalse; wantSoundName = qtrue; text = &buffer; while ( 1 ) { token = COM_ParseExt( text, qtrue ); if ( !token[0] ) { if (inSound) { CG_Error( "no concluding '}' in sound %s, file %s\n", sound.name, filename ); } return; } if ( !Q_strcasecmp( token, "{" ) ) { if (inSound) { CG_Error( "no concluding '}' in sound %s, file %s\n", sound.name, filename ); } if (wantSoundName) { CG_Error( "'{' found but not expected, after %s, file %s\n", sound.name, filename ); } inSound = qtrue; continue; } if ( !Q_strcasecmp( token, "}" ) ) { if (!inSound) { CG_Error( "'}' unexpected after sound %s, file %s\n", sound.name, filename ); } // end of a sound, copy it to the global list and stick it in the hashTable hash = generateHashValue( sound.name ); sound.nextHash = hashTable[hash]; soundScripts[numSoundScripts] = sound; hashTable[hash] = &soundScripts[numSoundScripts++]; if (numSoundScripts == MAX_SOUND_SCRIPTS) { CG_Error( "MAX_SOUND_SCRIPTS exceeded.\nReduce number of sound scripts.\n" ); } inSound = qfalse; wantSoundName = qtrue; continue; } if ( !inSound ) { // this is the identifier for a new sound if (!wantSoundName) { CG_Error( "'%s' unexpected after sound %s, file %s\n", token, sound.name, filename ); } memset( &sound, 0, sizeof(sound) ); Q_strncpyz( sound.name, token, sizeof(sound.name) ); wantSoundName = qfalse; sound.index = numSoundScripts; // setup the new sound defaults sound.channel = CHAN_AUTO; sound.attenuation = 1; // default to fade away with distance (for streaming sounds) // continue; } // we are inside a sound script if ( !Q_strcasecmp( token, "channel" ) ) { // ignore this now, just look for the channel identifiers explicitly continue; } if ( !Q_strcasecmp( token, "local" ) ) { sound.channel = CHAN_LOCAL; continue; } else if ( !Q_strcasecmp( token, "announcer" ) ) { sound.channel = CHAN_ANNOUNCER; continue; } else if ( !Q_strcasecmp( token, "body" ) ) { sound.channel = CHAN_BODY; continue; } else if ( !Q_strcasecmp( token, "voice" ) ) { sound.channel = CHAN_VOICE; continue; } else if ( !Q_strcasecmp( token, "weapon" ) ) { sound.channel = CHAN_WEAPON; continue; } else if ( !Q_strcasecmp( token, "item" ) ) { sound.channel = CHAN_ITEM; continue; } else if ( !Q_strcasecmp( token, "auto" ) ) { sound.channel = CHAN_AUTO; continue; } if ( !Q_strcasecmp( token, "global" ) ) { sound.attenuation = 0; continue; } if ( !Q_strcasecmp( token, "streaming" ) ) { sound.streaming = qtrue; continue; } if ( !Q_strcasecmp( token, "looping" ) ) { sound.looping = qtrue; continue; } if ( !Q_strcasecmp( token, "sound" ) ) { // grab a free scriptSound scriptSound = &soundScriptSounds[numSoundScriptSounds++]; if (numSoundScripts == MAX_SOUND_SCRIPT_SOUNDS) { CG_Error( "MAX_SOUND_SCRIPT_SOUNDS exceeded.\nReduce number of sound scripts.\n" ); } token = COM_ParseExt( text, qtrue ); Q_strncpyz( scriptSound->filename, token, sizeof(scriptSound->filename) ); scriptSound->lastPlayed = 0; scriptSound->sfxHandle = 0; scriptSound->next = sound.soundList; sound.soundList = scriptSound; continue; } } }
gltexture_t *Material_LoadTexture(Material_t *mMaterial, MaterialSkin_t *mCurrentSkin, char *cArg) { int iTextureFlags = TEXPREF_ALPHA|TEXPREF_MIPMAP; uint8_t *bTextureMap; // Check if it's trying to use a built-in texture. if (cArg[0] == '@') { cArg++; if (!Q_strcasecmp(cArg, "notexture")) return notexture; else if (!Q_strcasecmp(cArg, "lightmap")) { mMaterial->override_lightmap = true; mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].mttType = MATERIAL_TEXTURE_LIGHTMAP; return notexture; } else { Con_Warning("Attempted to set invalid internal texture! (%s)\n", mMaterial->cPath); return notexture; } } // Ensure we haven't loaded the texture in already... gltexture_t *gTexture = TexMgr_GetTexture(cArg); if (gTexture) #if 0 // Debugging { Con_Printf("Found already existing sample! (%s) (%s)", gTexture->name, mMaterial->cPath); return gTexture; } #else return gTexture; #endif bTextureMap = Image_LoadImage(cArg, &mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth, &mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight); if (bTextureMap) { // Warn about incorrect sizes. if ((mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth % 2) || (mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight % 2)) { Con_Warning("Texture size is not multiple of 2! (%s) (%ix%i)\n", cArg, mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth, mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight); #if 1 // Pad the image. iTextureFlags |= TEXPREF_PAD; #endif } if (mMaterial->iFlags & MATERIAL_FLAG_PRESERVE) iTextureFlags |= TEXPREF_PERSIST; if (mCurrentSkin->uiFlags & MATERIAL_FLAG_NEAREST) iTextureFlags |= TEXPREF_NEAREST; return TexMgr_LoadImage(NULL, cArg, mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth, mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight, SRC_RGBA, bTextureMap, cArg, 0, iTextureFlags); } Con_Warning("Failed to load texture! (%s) (%s)\n", cArg, mMaterial->cPath); return notexture; }
/* * Takes a key/value pair and sets * the binary values in an edict */ void ED_ParseField(const char *key, const char *value, edict_t *ent) { field_t *f; byte *b; float v; vec3_t vec; if (!key || !value) { return; } for (f = fields; f->name; f++) { if (!(f->flags & FFL_NOSPAWN) && !Q_strcasecmp(f->name, (char *)key)) { /* found it */ if (f->flags & FFL_SPAWNTEMP) { b = (byte *)&st; } else { b = (byte *)ent; } switch (f->type) { case F_LSTRING: *(char **)(b + f->ofs) = ED_NewString(value); break; case F_VECTOR: sscanf(value, "%f %f %f", &vec[0], &vec[1], &vec[2]); ((float *)(b + f->ofs))[0] = vec[0]; ((float *)(b + f->ofs))[1] = vec[1]; ((float *)(b + f->ofs))[2] = vec[2]; break; case F_INT: *(int *)(b + f->ofs) = (int)strtol(value, (char **)NULL, 10); break; case F_FLOAT: *(float *)(b + f->ofs) = (float)strtod(value, (char **)NULL); break; case F_ANGLEHACK: v = (float)strtod(value, (char **)NULL); ((float *)(b + f->ofs))[0] = 0; ((float *)(b + f->ofs))[1] = v; ((float *)(b + f->ofs))[2] = 0; break; case F_IGNORE: break; default: break; } return; } } gi.dprintf("%s is not a field\n", key); }
/* * ====================== * SV_Map * * the full syntax is: * * map [*]<map>$<startspot>+<nextserver> * * command from the console or progs. * Map can also be a.cin, .pcx, or .dm2 file * Nextserver is used to allow a cinematic to play, then proceed to * another level: * * map tram.cin+jail_e3 * ====================== */ void SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame) { char level[MAX_QPATH]; char *ch; int l; char spawnpoint[MAX_QPATH]; sv.loadgame = loadgame; sv.attractloop = attractloop; if ((sv.state == ss_dead) && !sv.loadgame) { SV_InitGame(); // the game is just starting } // r1ch fix: buffer overflow // strcpy (level, levelstring); strncpy(level, levelstring, sizeof(level) - 1); // if there is a + in the map, set nextserver to the remainder ch = strstr(level, "+"); if (ch) { *ch = 0; Cvar_Set("nextserver", va("gamemap \"%s\"", ch + 1)); } else { Cvar_Set("nextserver", ""); } //ZOID special hack for end game screen in coop mode if (Cvar_VariableValue("coop") && !Q_strcasecmp(level, "victory.pcx")) { Cvar_Set("nextserver", "gamemap \"*base1\""); } // if there is a $, use the remainder as a spawnpoint ch = strstr(level, "$"); if (ch) { *ch = 0; strcpy(spawnpoint, ch + 1); } else { spawnpoint[0] = 0; } // skip the end-of-unit flag if necessary if (level[0] == '*') { strcpy(level, level + 1); } l = strlen(level); #ifdef ROQ_SUPPORT if ((l > 4) && (!strcmp(level + l - 4, ".cin") || !strcmp(level + l - 4, ".roq"))) #else if ((l > 4) && !strcmp(level + l - 4, ".cin")) #endif // ROQ_SUPPORT { if (!dedicated->value) { #ifndef DEDICATED_ONLY SCR_BeginLoadingPlaque(); // for local system #endif } SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_cinematic, attractloop, loadgame); } else if ((l > 4) && !strcmp(level + l - 4, ".dm2")) { if (!dedicated->value) { #ifndef DEDICATED_ONLY SCR_BeginLoadingPlaque(); // for local system #endif } SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_demo, attractloop, loadgame); } else if ((l > 4) && !strcmp(level + l - 4, ".pcx")) { if (!dedicated->value) { #ifndef DEDICATED_ONLY SCR_BeginLoadingPlaque(); // for local system #endif } SV_BroadcastCommand("changing\n"); SV_SpawnServer(level, spawnpoint, ss_pic, attractloop, loadgame); } else { if (!dedicated->value) { #ifndef DEDICATED_ONLY SCR_BeginLoadingPlaque(); // for local system #endif } SV_BroadcastCommand("changing\n"); SV_SendClientMessages(); SV_SpawnServer(level, spawnpoint, ss_game, attractloop, loadgame); Cbuf_CopyToDefer(); } SV_BroadcastCommand("reconnect\n"); }
void Cmd_Bless(edict_t *ent) { int radius; float duration, cooldown; edict_t *target = NULL; if (debuginfo->value) gi.dprintf("DEBUG: %s just called Cmd_Bless()\n", ent->client->pers.netname); if(ent->myskills.abilities[BLESS].disable) return; //if (!G_CanUseAbilities(ent, ent->myskills.abilities[BLESS].current_level, BLESS_COST)) // return; if (!V_CanUseAbilities(ent, BLESS, BLESS_COST, true)) return; radius = SHAMAN_CURSE_RADIUS_BASE + (SHAMAN_CURSE_RADIUS_BONUS * ent->myskills.abilities[BLESS].current_level); duration = BLESS_DURATION_BASE + (BLESS_DURATION_BONUS * ent->myskills.abilities[BLESS].current_level); //Blessing self? if (Q_strcasecmp(gi.argv(1), "self") == 0) { if (HasFlag(ent)) { gi.cprintf(ent, PRINT_HIGH, "Can't use this while carrying the flag!\n"); return; } if (!curse_add(ent, ent, BLESS, 0, duration)) { gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n"); return; } target = ent; } else { target = curse_Attack(ent, BLESS, radius, duration, false); } if (target != NULL) { que_t *slot = NULL; //Finish casting the spell ent->client->ability_delay = level.time + BLESS_DELAY; ent->client->pers.inventory[power_cube_index] -= BLESS_COST; cooldown = 2.0 * duration; if (cooldown > 10.0) cooldown = 10.0; ent->myskills.abilities[BLESS].delay = level.time + cooldown; //Change the curse think to the bless think slot = que_findtype(target->curses, NULL, BLESS); if (slot) { slot->ent->think = Bless_think; slot->ent->nextthink = level.time + FRAMETIME; } //Notify the target if (target == ent) { gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration); } else if ((target->client) && !(target->svflags & SVF_MONSTER)) { gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration); gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->myskills.player_name, duration); } else { gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->classname, duration); } //Play the spell sound! gi.sound(target, CHAN_ITEM, gi.soundindex("curses/bless.wav"), 1, ATTN_NORM, 0); } }
/* =============== LoadBrush Converts a mapbrush to a bsp brush =============== */ brush_t *LoadBrush (mbrush_t *mb, int hullnum) { brush_t *b; int contents, NoOfTex = 0, I, TexNo[3], MipTex1, MipTex2, Hull; char *name, Str[512]; mface_t *f; CurrLine = mb->Line; // // check texture name for attributes // name = miptex[MipTex1 = texinfo[mb->faces->texinfo].miptex]; if (!Q_strcasecmp(name, "clip") && hullnum == 0) return NULL; // "clip" brushes don't show up in the draw hull if (name[0] == '*' && worldmodel) // entities never use water merging { if (!Q_strncasecmp(name+1,"lava",4)) contents = CONTENTS_LAVA; else if (!Q_strncasecmp(name+1,"slime",5)) contents = CONTENTS_SLIME; else contents = CONTENTS_WATER; } else if (!options.SolidMap && !Q_strncasecmp (name, "sky",3) && worldmodel && hullnum == 0) contents = CONTENTS_SKY; else contents = CONTENTS_SOLID; if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY) return NULL; // water brushes don't show up in clipping hulls // no seperate textures on clip hull // // create the faces // brush_faces = NULL; numbrushfaces = 0; for (f=mb->faces ; f ; f=f->next) { faces[numbrushfaces] = *f; if (hullnum) faces[numbrushfaces].texinfo = 0; numbrushfaces++; if (numbrushfaces == MAX_FACES) Message (MSGERR, "LoadBrush: numbrushfaces == MAX_FACES (%d) on line %d", MAX_FACES, CurrLine); } CreateBrushFaces (); if (!brush_faces) { strcpy(Str, name); // Find max 3 extra unique texture names for (f = mb->faces; f; f = f->next) { MipTex2 = texinfo[f->texinfo].miptex; if (NoOfTex < 3 && MipTex2 != MipTex1) { for (I = 0; I < NoOfTex; ++I) { if (MipTex2 == TexNo[I]) break; } if (I == NoOfTex) TexNo[NoOfTex++] = MipTex2; } } for (I = 0; I < NoOfTex; ++I) { strcat(Str, " "); strcat(Str, miptex[TexNo[I]]); } Message (MSGWARN, "Couldn't create brush on line %d with %d faces, %s", CurrLine, numbrushfaces, Str); return NULL; } Hull = hullnum == 0 ? options.visiblehull : hullnum; if (Hull || options.HullExpansion[1] > 0) { ExpandBrush (Hull); FreeBrushFaces(brush_faces); CreateBrushFaces (); } // // create the brush // b = AllocBrush (); b->contents = contents; b->faces = brush_faces; VectorCopy (brush_mins, b->mins); VectorCopy (brush_maxs, b->maxs); return b; }
void Cmd_Healing(edict_t *ent) { int radius; float duration; edict_t *target = NULL; if (debuginfo->value) gi.dprintf("DEBUG: %s just called Cmd_Healing()\n", ent->client->pers.netname); if(ent->myskills.abilities[HEALING].disable) return; if (!G_CanUseAbilities(ent, ent->myskills.abilities[HEALING].current_level, HEALING_COST)) return; radius = SHAMAN_CURSE_RADIUS_BASE + (SHAMAN_CURSE_RADIUS_BONUS * ent->myskills.abilities[HEALING].current_level); duration = HEALING_DURATION_BASE + (HEALING_DURATION_BONUS * ent->myskills.abilities[HEALING].current_level); //Blessing self? if (Q_strcasecmp(gi.argv(1), "self") == 0) { if (!curse_add(ent, ent, HEALING, 0, duration)) { gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n"); return; } target = ent; } else { target = curse_Attack(ent, HEALING, radius, duration, false); } if (target != NULL) { que_t *slot = NULL; //Finish casting the spell ent->client->ability_delay = level.time + HEALING_DELAY; ent->client->pers.inventory[power_cube_index] -= HEALING_COST; //Change the curse think to the healing think slot = que_findtype(target->curses, NULL, HEALING); if (slot) { slot->ent->think = Healing_think; slot->ent->nextthink = level.time + FRAMETIME; } //Notify the target if (target == ent) { gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED WITH %0.1f seconds OF HEALING!!\n", duration); } else if ((target->client) && !(target->svflags & SVF_MONSTER)) { gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED WITH %0.1f seconds OF HEALING!!\n", duration); gi.cprintf(ent, PRINT_HIGH, "Blessed %s with healing for %0.1f seconds.\n", target->myskills.player_name, duration); } else { gi.cprintf(ent, PRINT_HIGH, "Blessed %s with healing for %0.1f seconds.\n", target->classname, duration); } //Play the spell sound! gi.sound(target, CHAN_ITEM, gi.soundindex("curses/prayer.wav"), 1, ATTN_NORM, 0); } }
void Cmd_Deflect_f(edict_t *ent) { float duration; edict_t *target = ent; // default target is self if (!V_CanUseAbilities(ent, DEFLECT, DEFLECT_COST, true)) return; duration = DEFLECT_INITIAL_DURATION + DEFLECT_ADDON_DURATION * ent->myskills.abilities[DEFLECT].current_level; // bless the tank instead of the noclipped player if (PM_PlayerHasMonster(ent)) target = target->owner; //Blessing self? if (Q_strcasecmp(gi.argv(1), "self") == 0) { if (!curse_add(target, ent, DEFLECT, 0, duration)) { gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n"); return; } //target = ent; } else { target = curse_Attack(ent, DEFLECT, 512.0, duration, false); } if (target != NULL) { que_t *slot = NULL; //Finish casting the spell ent->client->ability_delay = level.time + DEFLECT_DELAY; ent->client->pers.inventory[power_cube_index] -= DEFLECT_COST; // ent->myskills.abilities[DEFLECT].delay = level.time + duration + DEFLECT_DELAY; //Change the curse think to the deflect think slot = que_findtype(target->curses, NULL, DEFLECT); if (slot) { slot->ent->think = deflect_think; slot->ent->nextthink = level.time + FRAMETIME; slot->ent->random = DEFLECT_INITIAL_PROJECTILE_CHANCE+DEFLECT_ADDON_HITSCAN_CHANCE*ent->myskills.abilities[DEFLECT].current_level; if (slot->ent->random > DEFLECT_MAX_PROJECTILE_CHANCE) slot->ent->random = DEFLECT_MAX_PROJECTILE_CHANCE; } //Notify the target if (target == ent) { gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n", duration); } else if ((target->client) && !(target->svflags & SVF_MONSTER)) { gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n\n", duration); gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", target->myskills.player_name, duration); } else { gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", V_GetMonsterName(target), duration); } //Play the spell sound! gi.sound(target, CHAN_ITEM, gi.soundindex("curses/prayer.wav"), 1, ATTN_NORM, 0); } }
/* Converts a mapbrush to a bsp brush */ brush_t *LoadBrush (mbrush_t *mb, int brushnum, int hullnum) { brush_t *b; int contents; char *name; mface_t *f; // // check texture name for attributes // for (f = mb->faces;f;f = f->next) { name = miptex[texinfo[f->texinfo].iMipTex]; if (hullnum == 0) // textures which don't show up in the drawing hull if(!Q_strcasecmp(name,"clip")) return NULL; } name = miptex[texinfo[mb->faces->texinfo].iMipTex]; if (name[0] == '*') // entities never use water merging { if(!Q_strncasecmp(name+1,"lava",4)) contents = BSP_CONTENTS_LAVA; else if(!Q_strncasecmp(name+1,"slime",5)) contents = BSP_CONTENTS_SLIME; else contents = BSP_CONTENTS_WATER; } else if (!Q_strncasecmp (name, "sky",3) && hullnum == 0) contents = BSP_CONTENTS_SKY; else contents = BSP_CONTENTS_SOLID; if (hullnum && contents != BSP_CONTENTS_SOLID && contents != BSP_CONTENTS_SKY) return NULL; // water brushes don't show up in clipping hulls // no seperate textures on clip hull // // create the faces // brush_faces = NULL; numbrushfaces = 0; for(f = mb->faces; f; f = f->next) { faces[numbrushfaces] = *f; if(hullnum) faces[numbrushfaces].texinfo = 0; numbrushfaces++; } if(hullnum) ExpandBrush (hullnum); CreateBrushFaces(); if (!brush_faces) { printf ("WARNING: couldn't create faces for brush %i in entity %i (incomplete brush?)\n", brushnum, (int)(CurrentEntity - entities)); return NULL; } // // create the brush // b = AllocBrush (); b->contents = contents; b->faces = brush_faces; VectorCopy (brush_mins, b->mins); VectorCopy (brush_maxs, b->maxs); // debugging code //printf("mapbrush\n"); //for (f=mb->faces ; f ; f=f->next) // printf("face %f %f %f %f \"%s\"\n", f->plane.normal[0], f->plane.normal[1], f->plane.normal[2], f->plane.dist, miptex[texinfo[f->texinfo].miptex]); //printf("bspbrush %i\n", numbrushfaces); //face_t *face; //for (face=b->faces ; face ; face=face->next) // printf("bspface %f %f %f %f\n", mapplanes[face->planenum].normal[0], mapplanes[face->planenum].normal[1], mapplanes[face->planenum].normal[2], mapplanes[face->planenum].dist); return b; }
void LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y; int len, full_size; int pcx_width, pcx_height; qboolean image_issues = false; int dataByte, runLength; byte *out, *pix; char filename[256]; Q_strlcpy(filename, origname, sizeof(filename)); /* Add the extension */ if (strcmp(COM_FileExtension(filename), "pcx")) { Q_strlcat(filename, ".pcx", sizeof(filename)); } *pic = NULL; if (palette) { *palette = NULL; } /* load the file */ len = ri.FS_LoadFile(filename, (void **)&raw); if (!raw || len < sizeof(pcx_t)) { R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename); return; } /* parse the PCX file */ pcx = (pcx_t *)raw; pcx->xmin = LittleShort(pcx->xmin); pcx->ymin = LittleShort(pcx->ymin); pcx->xmax = LittleShort(pcx->xmax); pcx->ymax = LittleShort(pcx->ymax); pcx->hres = LittleShort(pcx->hres); pcx->vres = LittleShort(pcx->vres); pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); pcx->palette_type = LittleShort(pcx->palette_type); raw = &pcx->data; pcx_width = pcx->xmax - pcx->xmin; pcx_height = pcx->ymax - pcx->ymin; if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) || (pcx->encoding != 1) || (pcx->bits_per_pixel != 8) || (pcx_width >= 4096) || (pcx_height >= 4096)) { R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename); ri.FS_FreeFile(pcx); return; } full_size = (pcx_height + 1) * (pcx_width + 1); out = malloc(full_size); if (!out) { R_Printf(PRINT_ALL, "Can't allocate\n"); ri.FS_FreeFile(pcx); return; } *pic = out; pix = out; if (palette) { *palette = malloc(768); if (!(*palette)) { R_Printf(PRINT_ALL, "Can't allocate\n"); free(out); ri.FS_FreeFile(pcx); return; } if (len > 768) { memcpy(*palette, (byte *)pcx + len - 768, 768); } else { image_issues = true; } } if (width) { *width = pcx_width + 1; } if (height) { *height = pcx_height + 1; } for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1) { for (x = 0; x <= pcx_width; ) { if (raw - (byte *)pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; if (raw - (byte *)pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; } else { runLength = 1; } while (runLength-- > 0) { if ((*pic + full_size) <= (pix + x)) { // no place for write image_issues = true; x += runLength; runLength = 0; } else { pix[x++] = dataByte; } } } } if (raw - (byte *)pcx > len) { R_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename); free(*pic); *pic = NULL; } else if(pcx_width == 319 && pcx_height == 239 && Q_strcasecmp(origname, "pics/quit.pcx") == 0 && Com_BlockChecksum(pcx, len) == 3329419434u) { // it's the quit screen, and the baseq2 one (identified by checksum) // so fix it fixQuitScreen(*pic); } if (image_issues) { R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename); } ri.FS_FreeFile(pcx); }
qsocket_t *NET_Connect (char *host) { qsocket_t *ret; int n; int numdrivers = net_numdrivers; SetNetTime(); if (host && *host == 0) host = NULL; if (host) { if (Q_strcasecmp (host, "local") == 0) { numdrivers = 1; goto JustDoIt; } if (hostCacheCount) { for (n = 0; n < hostCacheCount; n++) if (Q_strcasecmp (host, hostcache[n].name) == 0) { host = hostcache[n].cname; break; } if (n < hostCacheCount) goto JustDoIt; } } slistSilent = host ? true : false; NET_Slist_f (); while(slistInProgress) NET_Poll(); if (host == NULL) { if (hostCacheCount != 1) return NULL; host = hostcache[0].cname; Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host); } if (hostCacheCount) for (n = 0; n < hostCacheCount; n++) if (Q_strcasecmp (host, hostcache[n].name) == 0) { host = hostcache[n].cname; break; } JustDoIt: for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++) { if (net_drivers[net_driverlevel].initialized == false) continue; ret = dfunc.Connect (host); if (ret) return ret; } if (host) { Con_Printf("\n"); PrintSlistHeader(); PrintSlist(); PrintSlistTrailer(); } return NULL; }
static void CD_f() { char *command; int cdstate; if(Cmd_Argc() < 2) return; command = Cmd_Argv(1); if(!Q_strcasecmp(command,"on")) { enabled = true; } if(!Q_strcasecmp(command,"off")) { if(!cd_id) return; cdstate = SDL_CDStatus(cd_id); if((cdstate == CD_PLAYING) || (cdstate == CD_PAUSED)) CDAudio_Stop(); enabled = false; return; } if(!Q_strcasecmp(command,"play")) { CDAudio_Play(Q_atoi(Cmd_Argv(2)),false); return; } if(!Q_strcasecmp(command,"loop")) { CDAudio_Play(Q_atoi(Cmd_Argv(2)),true); return; } if(!Q_strcasecmp(command,"stop")) { CDAudio_Stop(); return; } if(!Q_strcasecmp(command,"pause")) { CDAudio_Pause(); return; } if(!Q_strcasecmp(command,"resume")) { CDAudio_Resume(); return; } if(!Q_strcasecmp(command,"eject")) { CDAudio_Eject(); return; } if(!Q_strcasecmp(command,"info")) { if(!cd_id) return; cdstate = SDL_CDStatus(cd_id); Con_Printf("%d tracks\n",cd_id->numtracks); if(cdstate == CD_PLAYING) Con_Printf("Currently %s track %d\n", playLooping ? "looping" : "playing", cd_id->cur_track+1); else if(cdstate == CD_PAUSED) Con_Printf("Paused %s track %d\n", playLooping ? "looping" : "playing", cd_id->cur_track+1); return; } }
void Master_SetMaster_f() { int AreAdding; const char * arg_1, * arg_2; int port; netadr_t netaddress; master_server_t * ptr, * ptr2; if(Cmd_Argc() < 2 || Cmd_Argc() > 4) { Con_Printf("Setmaster <add | remove | enable | disable> <IP:port>\n"); Con_Printf(" Current master list:\n"); for(ptr = masterlist; ptr != NULL; ptr = ptr->next) { Con_Printf(" %s\n", NET_AdrToString(ptr->address)); } Con_Printf(" End if list\n"); return; } arg_1 = Cmd_Argv(1); if(arg_1[0] == '\0') { return; } if(Q_strcasecmp(arg_1, "disable") == 0) { gfNoMasterServer = 1; return; } if(Q_strcasecmp(arg_1, "enable") == 0) { gfNoMasterServer = 0; return; } if(Q_strcasecmp(arg_1, "add") == 0) { AreAdding = 1; } else if(Q_strcasecmp(arg_1, "remove") == 0) { AreAdding = 0; } else { Con_Printf("Setmaster: Unknown command \"%s\".\n", arg_1); return; } arg_2 = Cmd_Argv(2); if(Cmd_Argc() == 4) { port = Q_atoi(Cmd_Argv(3)); if(port < 1 || port > 65535) { Con_Printf("Setmaster: Invalid port. Ports can't be larger than 65535.\n"); return; } } else { port = 27010; } if(NET_StringToAdr(arg_2, &netaddress) == 0) { Con_Printf("Setmaster: Passed address could not be processed by StringToAdr.\n"); return; } netaddress.port = port; if(AreAdding) { Master_Init(); Master_AddServer(&netaddress); gfNoMasterServer = 0; Con_Printf("Master server %s:%u added.\n", arg_2, port); } else { //case 1: first node. if(NET_CompareAdr(masterlist->address, netaddress) != 0) { ptr = masterlist; masterlist = masterlist->next; Q_Free(ptr); return; } //case 2: some node afterwards for(ptr = masterlist; ptr->next != NULL; ptr = ptr->next) { if(NET_CompareAdr(ptr->next->address, netaddress) != 0) { ptr2 = ptr->next; ptr->next = ptr->next->next; Q_Free(ptr2); return; } } //case 3: not here Con_Printf("Master %s:%u couldn't be removed. Couldn't find it.\n", arg_2, port); } }
/** * @brief Initialize a node behaviour memory, after registration, and before unsing it. * @param behaviour Behaviour to initialize */ void UI_InitializeNodeBehaviour (uiBehaviour_t* behaviour) { if (behaviour->isInitialized) return; /* everything inherits 'abstractnode' */ if (behaviour->extends == NULL && !Q_streq(behaviour->name, "abstractnode")) { behaviour->extends = "abstractnode"; } if (behaviour->extends) { int i = 0; /** TODO Find a way to remove that, if possible */ behaviour->super = UI_GetNodeBehaviour(behaviour->extends); UI_InitializeNodeBehaviour(behaviour->super); while (qtrue) { const size_t pos = virtualFunctions[i]; uintptr_t superFunc; uintptr_t func; if (pos == -1) break; /* cache super function if we don't overwrite it */ superFunc = *(uintptr_t*)((byte*)behaviour->super + pos); func = *(uintptr_t*)((byte*)behaviour + pos); if (func == 0 && superFunc != 0) *(uintptr_t*)((byte*)behaviour + pos) = superFunc; i++; } } /* sort properties by alphabet */ if (behaviour->localProperties) { int i = 0; const value_t* previous; const value_t** oldmemory = behaviour->localProperties; behaviour->localProperties = UI_AllocHunkMemory(sizeof(value_t*) * (behaviour->propertyCount+1), STRUCT_MEMORY_ALIGN, qfalse); if (behaviour->localProperties == NULL) { Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: UI memory hunk exceeded - increase the size"); } previous = NULL; for (i = 0; i < behaviour->propertyCount; i++) { const value_t* better = NULL; const value_t** current; /* search the next element after previous */ for (current = oldmemory; *current != NULL; current++) { if (previous != NULL && Q_strcasecmp(previous->string, (*current)->string) >= 0) { continue; } if (better == NULL || Q_strcasecmp(better->string, (*current)->string) >= 0) { better = *current; } } previous = better; behaviour->localProperties[i] = better; } behaviour->localProperties[behaviour->propertyCount] = NULL; Mem_Free(oldmemory); } /* property must not overwrite another property */ if (behaviour->super && behaviour->localProperties) { const value_t** property = behaviour->localProperties; while (*property) { const value_t *p = UI_GetPropertyFromBehaviour(behaviour->super, (*property)->string); #if 0 /**< @todo not possible at the moment, not sure its the right way */ const uiBehaviour_t *b = UI_GetNodeBehaviour(current->string); #endif if (p != NULL) Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' overwrite another property", (*property)->string, behaviour->name); #if 0 /**< @todo not possible at the moment, not sure its the right way */ if (b != NULL) Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' use the name of an existing node behaviour", (*property)->string, behaviour->name); #endif property++; } } /* Sanity: A property must not be outside the node memory */ if (behaviour->localProperties) { const int size = sizeof(uiNode_t) + behaviour->extraDataSize; const value_t** property = behaviour->localProperties; while (*property) { if ((*property)->type != V_UI_NODEMETHOD && (*property)->ofs + (*property)->size > size) Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' is outside the node memory. The C code need a fix.", (*property)->string, behaviour->name); property++; } } behaviour->isInitialized = qtrue; }
void Master_Init() { int i, SkipSection, tempport; static int HaveConfigured = 0; char * filep; const char * curfilep; netadr_t tempadr; if(HaveConfigured != 0 || gfNoMasterServer != 0) { return; } HaveConfigured = 1; if(COM_CheckParmCase("-nomaster") != 0 || global_svs.allocated_client_slots <= 1) { Con_Printf("%s: Master server comm disabled.\n", __FUNCTION__); gfNoMasterServer = 0; return; //and don't check again, ever. } MasterHeartbeatTimeout = 15; i = COM_CheckParmCase("-comm"); if(i != 0 && i+1 < global_com_argc) { filep = COM_LoadFileForMe(global_com_argv[i+1], NULL); } else { filep = COM_LoadFileForMe("valvecomm.lst", NULL); if(filep == NULL) { filep = COM_LoadFileForMe("woncomm.lst", NULL); } } if(filep == NULL) { Con_Printf("%s: Couldn't load comm file. Disabling masters--fix it.\n", __FUNCTION__); return; } curfilep = filep; i = 0; while(1) { curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0') { break; } SkipSection = 1; if(Q_strcasecmp("master", global_com_token) == 0) { SkipSection = 0; } curfilep = COM_Parse(curfilep); if(Q_strcmp("{", global_com_token) != 0) { break; } while(1) { curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0' || Q_strcmp("}", global_com_token) == 0) { break; } if(SkipSection == 0 && NET_StringToAdr(global_com_token, &tempadr) == 0) { break; } //We just (maybe) parsed the server name, if you missed it. Now for the port. curfilep = COM_Parse(curfilep); if(Q_strcmp(":", global_com_token) != 0) { break; } curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0') { break; } if(SkipSection == 0) { tempport = Q_atoi(global_com_token); if(tempport < 1 || tempport > 65535) { tempport = 27010; } tempadr.port = tempport; Con_Printf("%s: Adding master server %s.\n", __FUNCTION__, NET_AdrToString(tempadr)); //all that work to avoid needless string copying, all gone :) Master_AddServer(&tempadr); i++; } } } COM_FreeFile(filep); if(i == 0) { Con_Printf("%s: Didn't parse any masters. Disabling master comm.\n", __FUNCTION__); gfNoMasterServer = 0; } }
/* * Objects need to be moved back on a failed push, * otherwise riders would continue to slide. */ qboolean SV_Push(edict_t *pusher, vec3_t move, vec3_t amove) { int i, e; edict_t *check, *block; pushed_t *p; vec3_t org, org2, move2, forward, right, up; vec3_t realmins, realmaxs; if (!pusher) { return false; } /* clamp the move to 1/8 units, so the position will be accurate for client side prediction */ for (i = 0; i < 3; i++) { float temp; temp = move[i] * 8.0; if (temp > 0.0) { temp += 0.5; } else { temp -= 0.5; } move[i] = 0.125 * (int)temp; } /* we need this for pushing things later */ VectorSubtract(vec3_origin, amove, org); AngleVectors(org, forward, right, up); /* save the pusher's original position */ pushed_p->ent = pusher; VectorCopy(pusher->s.origin, pushed_p->origin); VectorCopy(pusher->s.angles, pushed_p->angles); if (pusher->client) { pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW]; } pushed_p++; /* move the pusher to it's final position */ VectorAdd(pusher->s.origin, move, pusher->s.origin); VectorAdd(pusher->s.angles, amove, pusher->s.angles); gi.linkentity(pusher); /* Create a real bounding box for rotating brush models. */ RealBoundingBox(pusher, realmins, realmaxs); /* see if any solid entities are inside the final position */ check = g_edicts + 1; for (e = 1; e < globals.num_edicts; e++, check++) { if (!check->inuse) { continue; } if ((check->movetype == MOVETYPE_PUSH) || (check->movetype == MOVETYPE_STOP) || (check->movetype == MOVETYPE_NONE) || (check->movetype == MOVETYPE_NOCLIP)) { continue; } if (!check->area.prev) { continue; /* not linked in anywhere */ } /* if the entity is standing on the pusher, it will definitely be moved */ if (check->groundentity != pusher) { /* see if the ent needs to be tested */ if ((check->absmin[0] >= realmaxs[0]) || (check->absmin[1] >= realmaxs[1]) || (check->absmin[2] >= realmaxs[2]) || (check->absmax[0] <= realmins[0]) || (check->absmax[1] <= realmins[1]) || (check->absmax[2] <= realmins[2])) { continue; } /* see if the ent's bbox is inside the pusher's final position */ if (!SV_TestEntityPosition(check)) { continue; } } if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher)) { /* move this entity */ pushed_p->ent = check; VectorCopy(check->s.origin, pushed_p->origin); VectorCopy(check->s.angles, pushed_p->angles); pushed_p++; /* try moving the contacted entity */ VectorAdd(check->s.origin, move, check->s.origin); if (check->client) { check->client->ps.pmove.delta_angles[YAW] += amove[YAW]; } /* figure movement due to the pusher's amove */ VectorSubtract(check->s.origin, pusher->s.origin, org); org2[0] = DotProduct(org, forward); org2[1] = -DotProduct(org, right); /* Quirk for blocking Elevators when running under amd64. This is most likey caused by a too high float precision. -_- */ if (((pusher->s.number == 285) && (Q_strcasecmp(level.mapname, "xcompnd2") == 0)) || ((pusher->s.number == 520) && (Q_strcasecmp(level.mapname, "xsewer2") == 0))) { org2[2] = DotProduct(org, up) + 2; } else { org2[2] = DotProduct(org, up); } VectorSubtract(org2, org, move2); VectorAdd(check->s.origin, move2, check->s.origin); /* may have pushed them off an edge */ if (check->groundentity != pusher) { check->groundentity = NULL; } block = SV_TestEntityPosition(check); if (!block) { /* pushed ok */ gi.linkentity(check); /* impact? */ continue; } /* if it is ok to leave in the old position, do it this is only relevent for riding entities, not pushed */ VectorSubtract(check->s.origin, move, check->s.origin); block = SV_TestEntityPosition(check); if (!block) { pushed_p--; continue; } } /* save off the obstacle so we can call the block function */ obstacle = check; /* move back any entities we already moved go backwards, so if the same entity was pushed twice, it goes back to the original position */ for (p = pushed_p - 1; p >= pushed; p--) { VectorCopy(p->origin, p->ent->s.origin); VectorCopy(p->angles, p->ent->s.angles); if (p->ent->client) { p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw; } gi.linkentity(p->ent); } return false; } /* see if anything we moved has touched a trigger */ for (p = pushed_p - 1; p >= pushed; p--) { G_TouchTriggers(p->ent); } return true; }
/** * Take a screenshot of the frame buffer * @param[in] x * @param[in] y * @param[in] width * @param[in] height * @param[in] filename Force to use a filename. Else NULL to autogen a filename * @param[in] ext Force to use an image format (tga/png/jpg). Else NULL to use value of r_screenshot_format */ void R_ScreenShot (int x, int y, int width, int height, const char *filename, const char *ext) { char checkName[MAX_OSPATH]; int type, shotNum, quality = 100; byte *buffer; qFILE f; int rowPack; glGetIntegerv(GL_PACK_ALIGNMENT, &rowPack); glPixelStorei(GL_PACK_ALIGNMENT, 1); /* Find out what format to save in */ if (ext == NULL) ext = r_screenshot_format->string; if (!Q_strcasecmp(ext, "png")) type = SSHOTTYPE_PNG; else if (!Q_strcasecmp(ext, "jpg")) type = SSHOTTYPE_JPG; else type = SSHOTTYPE_TGA_COMP; /* Set necessary values */ switch (type) { case SSHOTTYPE_TGA_COMP: Com_Printf("Taking TGA screenshot...\n"); ext = "tga"; break; case SSHOTTYPE_PNG: Com_Printf("Taking PNG screenshot...\n"); ext = "png"; break; case SSHOTTYPE_JPG: if (Cmd_Argc() == 3) quality = atoi(Cmd_Argv(2)); else quality = r_screenshot_jpeg_quality->integer; if (quality > 100 || quality <= 0) quality = 100; Com_Printf("Taking JPG screenshot (at %i%% quality)...\n", quality); ext = "jpg"; break; } /* Find a file name to save it to */ if (filename) { Com_sprintf(checkName, sizeof(checkName), "scrnshot/%s.%s", filename, ext); } else { for (shotNum = 0; shotNum < 1000; shotNum++) { Com_sprintf(checkName, sizeof(checkName), "scrnshot/ufo%i%i.%s", shotNum / 10, shotNum % 10, ext); if (FS_CheckFile("%s", checkName) == -1) break; } if (shotNum == 1000) { Com_Printf("R_ScreenShot_f: screenshot limit (of 1000) exceeded!\n"); return; } } /* Open it */ FS_OpenFile(checkName, &f, FILE_WRITE); if (!f.f) { Com_Printf("R_ScreenShot_f: Couldn't create file: %s\n", checkName); return; } /* Allocate room for a copy of the framebuffer */ buffer = (byte *)Mem_PoolAlloc(width * height * 3, vid_imagePool, 0); if (!buffer) { Com_Printf("R_ScreenShot_f: Could not allocate %i bytes for screenshot!\n", width * height * 3); FS_CloseFile(&f); return; } /* Read the framebuffer into our storage */ glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); R_CheckError(); /* Write */ switch (type) { case SSHOTTYPE_TGA_COMP: R_WriteCompressedTGA(&f, buffer, width, height); break; case SSHOTTYPE_PNG: R_WritePNG(&f, buffer, width, height); break; case SSHOTTYPE_JPG: R_WriteJPG(&f, buffer, width, height, quality); break; } /* Finish */ FS_CloseFile(&f); Mem_Free(buffer); Com_Printf("Wrote %s to %s\n", checkName, FS_Gamedir()); glPixelStorei(GL_PACK_ALIGNMENT, rowPack); }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ void SV_GameMap_f (void) { char *map; int i, l; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame map = Cmd_Argv(1); if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame ("current"); } else { // save the map just exited if (sv.state == ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells savedInuse = malloc(maxclients->value * sizeof(qboolean)); for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) cl->edict->inuse = savedInuse[i]; free (savedInuse); } } // start up the next map SV_Map (false, Cmd_Argv(1), false ); // archive server state strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); // copy off the level to the autosave slot // Knightmare- don't do this in deathmatch or for cinematics l = strlen(map); //l = strcspn(map, "+"); if (!dedicated->value && !Cvar_VariableValue("deathmatch") && Q_strcasecmp (map+l-4, ".cin") && Q_strcasecmp (map+l-4, ".roq") && Q_strcasecmp (map+l-4, ".pcx")) { SV_WriteServerFile (true); SV_CopySaveGame ("current", "kmq2save0"); } }
/* ================= G_ScriptAction_PlayAnim syntax: playanim <startframe> <endframe> [looping <FOREVER/duration>] [rate <FPS>] NOTE: all source animations must be at 20fps ================= */ qboolean G_ScriptAction_PlayAnim( gentity_t *ent, const char* params ) { const char* pString; char* token; char tokens[2][MAX_QPATH]; int i, endtime = 0; // TTimo: init qboolean looping = qfalse, forever = qfalse; int startframe, endframe, idealframe; int rate = 20; if ( ( ent->scriptStatus.scriptFlags & SCFL_ANIMATING ) && ( ent->scriptStatus.scriptStackChangeTime == level.time ) ) { // this is a new call, so cancel the previous animation ent->scriptStatus.scriptFlags &= ~SCFL_ANIMATING; } pString = params; for ( i = 0; i < 2; i++ ) { token = COM_ParseExt( &pString, qfalse ); if ( !token || !token[0] ) { G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" ); return qtrue; } else { Q_strncpyz( tokens[i], token, sizeof( tokens[i] ) ); } } startframe = atoi( tokens[0] ); endframe = atoi( tokens[1] ); // check for optional parameters token = COM_ParseExt( &pString, qfalse ); if ( token[0] ) { if ( !Q_strcasecmp( token, "looping" ) ) { looping = qtrue; token = COM_ParseExt( &pString, qfalse ); if ( !token || !token[0] ) { G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" ); return qtrue; } if ( !Q_strcasecmp( token, "untilreachmarker" ) ) { if ( level.time < ent->s.pos.trTime + ent->s.pos.trDuration ) { endtime = level.time + 100; } else { endtime = 0; } } else if ( !Q_strcasecmp( token, "forever" ) ) { ent->scriptStatus.animatingParams = params; ent->scriptStatus.scriptFlags |= SCFL_ANIMATING; endtime = level.time + 100; // we don't care when it ends, since we are going forever! forever = qtrue; } else { endtime = ent->scriptStatus.scriptStackChangeTime + atoi( token ); } token = COM_ParseExt( &pString, qfalse ); } if ( token[0] && !Q_strcasecmp( token, "rate" ) ) { token = COM_ParseExt( &pString, qfalse ); if ( !token[0] ) { G_Error( "G_Scripting: playanim has RATE parameter without an actual rate specified" ); } rate = atoi( token ); } if ( !looping ) { endtime = ent->scriptStatus.scriptStackChangeTime + ( ( endframe - startframe ) * ( 1000 / 20 ) ); } } idealframe = startframe + (int)c::floor( (float)( level.time - ent->scriptStatus.scriptStackChangeTime ) / ( 1000.0 / (float)rate ) ); if ( looping ) { ent->s.frame = startframe + ( idealframe - startframe ) % ( endframe - startframe ); ent->s.eFlags |= EF_MOVER_ANIMATE; } else { if ( idealframe > endframe ) { ent->s.frame = endframe; ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop interpolation, since we have gone passed the endframe } else { ent->s.frame = idealframe; ent->s.eFlags |= EF_MOVER_ANIMATE; } } if ( forever ) { ent->s.eFlags |= EF_MOVER_ANIMATE; return qtrue; // continue to the next command } if ( endtime <= level.time ) { ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop animating return qtrue; } else { return qfalse; } }
static void Test_f(void) { char *host; int n; int max = MAX_SCOREBOARD; struct qsockaddr sendaddr; if (testInProgress) { return; } host = Cmd_Argv(1); if (host && hostCacheCount) { for (n = 0; n < hostCacheCount; n++) if (Q_strcasecmp(host, hostcache[n].name) == 0) { if (hostcache[n].driver != myDriverLevel) { continue; } net_landriverlevel = hostcache[n].ldriver; max = hostcache[n].maxusers; Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); break; } if (n < hostCacheCount) { goto JustDoIt; } } for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { if (!net_landrivers[net_landriverlevel].initialized) { continue; } // see if we can resolve the host name if (dfunc.GetAddrFromName(host, &sendaddr) != -1) { break; } } if (net_landriverlevel == net_numlandrivers) { return; } JustDoIt: testSocket = dfunc.OpenSocket(0); if (testSocket == -1) { return; } testInProgress = true; testPollCount = 20; testDriver = net_landriverlevel; for (n = 0; n < max; n++) { SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO); MSG_WriteByte(&net_message, n); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); dfunc.Write(testSocket, net_message.data, net_message.cursize, &sendaddr); } SZ_Clear(&net_message); SchedulePollProcedure(&testPollProcedure, 0.1); }
/* ================= G_ScriptAction_FaceAngles syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME> [ACCEL/DECCEL] The entity will face the given angles, taking <duration> to get there. If the GOTOTIME is given instead of a timed duration, the duration calculated from the last gotomarker command will be used instead. ================= */ qboolean G_ScriptAction_FaceAngles( gentity_t *ent, const char* params ) { const char* pString; char* token; int duration, i; vec3_t diff; vec3_t angles; int trType = TR_LINEAR_STOP; if ( !params || !params[0] ) { G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" ); } if ( ent->scriptStatus.scriptStackChangeTime == level.time ) { pString = params; for ( i = 0; i < 3; i++ ) { token = COM_Parse( &pString ); if ( !token || !token[0] ) { G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" ); } angles[i] = atoi( token ); } token = COM_Parse( &pString ); if ( !token || !token[0] ) { G_Error( "G_Scripting: faceangles requires a <pitch> <yaw> <roll> <duration/GOTOTIME>\n" ); } if ( !Q_strcasecmp( token, "gototime" ) ) { duration = ent->s.pos.trDuration; } else { duration = atoi( token ); } token = COM_Parse( &pString ); if ( token && token[0] ) { if ( !Q_strcasecmp( token, "accel" ) ) { trType = TR_ACCELERATE; } if ( !Q_strcasecmp( token, "deccel" ) ) { trType = TR_DECCELERATE; } } for ( i = 0; i < 3; i++ ) { diff[i] = AngleDifference( angles[i], ent->s.angles[i] ); while ( diff[i] > 180 ) diff[i] -= 360; while ( diff[i] < -180 ) diff[i] += 360; } VectorCopy( ent->s.angles, ent->s.apos.trBase ); if ( duration ) { VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta ); } else { VectorClear( ent->s.apos.trDelta ); } ent->s.apos.trDuration = duration; ent->s.apos.trTime = level.time; ent->s.apos.trType = TR_LINEAR_STOP; if ( trType != TR_LINEAR_STOP ) { // accel / deccel logic // calc the speed from duration and start/end delta for ( i = 0; i < 3; i++ ) { ent->s.apos.trDelta[i] = 2.0 * 1000.0 * diff[i] / (float)duration; } ent->s.apos.trType = trType_t (trType); } } else if ( ent->s.apos.trTime + ent->s.apos.trDuration <= level.time ) { // finished turning BG_EvaluateTrajectory( &ent->s.apos, ent->s.apos.trTime + ent->s.apos.trDuration, ent->s.angles ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); VectorCopy( ent->s.angles, ent->r.currentAngles ); ent->s.apos.trTime = level.time; ent->s.apos.trDuration = 0; ent->s.apos.trType = TR_STATIONARY; VectorClear( ent->s.apos.trDelta ); script_linkentity( ent ); return qtrue; } BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles ); script_linkentity( ent ); return qfalse; }
static void CD_f (void) { char *command; int ret; int n; if (Cmd_Argc() < 2) return; command = Cmd_Argv (1); if (Q_strcasecmp(command, "on") == 0) { enabled = true; return; } if (Q_strcasecmp(command, "off") == 0) { if (playing) CDAudio_Stop(); enabled = false; return; } if (Q_strcasecmp(command, "reset") == 0) { enabled = true; if (playing) CDAudio_Stop(); for (n = 0; n < 100; n++) remap[n] = n; CDAudio_GetAudioDiskInfo(); return; } if (Q_strcasecmp(command, "remap") == 0) { ret = Cmd_Argc() - 2; if (ret <= 0) { for (n = 1; n < 100; n++) if (remap[n] != n) Con_Printf(" %u -> %u\n", n, remap[n]); return; } for (n = 1; n <= ret; n++) remap[n] = Q_atoi(Cmd_Argv (n+1)); return; } if (Q_strcasecmp(command, "close") == 0) { CDAudio_CloseDoor(); return; } if (!cdValid) { CDAudio_GetAudioDiskInfo(); if (!cdValid) { Con_Printf("No CD in player.\n"); return; } } if (Q_strcasecmp(command, "play") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); return; } if (Q_strcasecmp(command, "loop") == 0) { CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); return; } if (Q_strcasecmp(command, "stop") == 0) { CDAudio_Stop(); return; } if (Q_strcasecmp(command, "pause") == 0) { CDAudio_Pause(); return; } if (Q_strcasecmp(command, "resume") == 0) { CDAudio_Resume(); return; } if (Q_strcasecmp(command, "eject") == 0) { if (playing) CDAudio_Stop(); CDAudio_Eject(); cdValid = false; return; } if (Q_strcasecmp(command, "info") == 0) { Con_Printf("%u tracks\n", maxTrack); if (playing) Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); else if (wasPlaying) Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); Con_Printf("Volume is %f\n", cdvolume); return; } }
/* DESCRIPTION: COM_InitArgv // LOCATION: common.c // PATH: Sys_Init->COM_InitArgv // // Rather than describe what this does, should do, etc. I'll point you to // sys_initargv instead. Our mission is simply to tokenize the (non-permenant?) // string given to us and assign its entries to host_pams.argv and global_com_argv. */ void COM_InitArgv(char *argvs) { //These static variables are referred to through pointers in global_com_argv a lot. //Todo: remove limits by dynamically allocating this memory. static char com_cmdline[0x101] = ""; static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; static char *safeargvs[NUM_SAFE_ARGVS] = {"-dibonly", "-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse" }; char *startofstring; char *argvposition; unsigned int NumParsedArgs = 1; unsigned int lengthcounter = 0; unsigned int com_cmdlinecounter = 0; startofstring = argvposition = argvs; largv[0] = ""; //dunno why, it just does, probably to ease off by one errors while((*argvposition) != '\0' && NumParsedArgs < MAX_NUM_ARGVS) { if(isgraph(*argvposition) == 0) { if (lengthcounter == 0) { //start and position are at the same place startofstring++; argvposition++; } else { lengthcounter++; if (com_cmdlinecounter+lengthcounter < 0x100) { *argvposition = '\0'; //cap that string Q_memcpy(com_cmdline+com_cmdlinecounter, startofstring, lengthcounter); largv[NumParsedArgs] = com_cmdlinecounter + com_cmdline; com_cmdlinecounter += lengthcounter; lengthcounter = 0; NumParsedArgs++; } argvposition++; //next token, whether we copied the old one or not startofstring = argvposition; } } else { lengthcounter++; argvposition++; } } //and the last one if applicable (likely true) if((*argvposition) == '\0' && lengthcounter > 0 && com_cmdlinecounter+lengthcounter < 0x100) { Q_memcpy(com_cmdline+com_cmdlinecounter, startofstring, lengthcounter); largv[NumParsedArgs] = com_cmdlinecounter + com_cmdline; NumParsedArgs++; } //That was fun. We parsed our string (as much as we could at least) and //assigned its values to largv. //NumParsedArgs is still useful. Other vars are free //for generic counter usage for(lengthcounter = 0; (lengthcounter < MAX_NUM_ARGVS) && (lengthcounter < NumParsedArgs); lengthcounter++) { if(Q_strcasecmp("-safe", largv[lengthcounter]) == 0) { com_cmdlinecounter = 1; break; } } if(com_cmdlinecounter == 1) { com_cmdlinecounter = 0; while(com_cmdlinecounter < NUM_SAFE_ARGVS) { largv[NumParsedArgs] = safeargvs[com_cmdlinecounter]; com_cmdlinecounter++; NumParsedArgs++; } } largv[NumParsedArgs] = " "; NumParsedArgs++; host_parms.argc = global_com_argc = NumParsedArgs; host_parms.argv = global_com_argv = largv; }
//-------------------------------------------------------------------------------------------------------------- void DownloadManager::Queue( const char *baseURL, const char *gamePath ) { bool bAsHTTP = false; if ( !gamePath ) { return; } #ifndef _DEBUG if ( sv.IsActive() ) { return; // don't try to download things for the local server (in case a map is missing sounds etc that // aren't needed to play. } #endif // only http downloads if ( baseURL && (!Q_strnicmp( baseURL, "http://", 7 ) || !Q_strnicmp( baseURL, "https://", 8 )) ) { bAsHTTP = true; } if ( g_pFileSystem->FileExists( gamePath ) ) { return; // don't download existing files } if ( Q_strstr( gamePath, "//" ) ) { return; } if ( Q_strstr( gamePath, "\\\\" ) ) { return; } if ( Q_strstr( gamePath, ":" ) ) { return; } if ( Q_strstr( gamePath, "lua/" ) ) return; // don't download into lua/ folder if ( Q_strstr( gamePath, "gamemodes/" ) ) return; // don't download into gamemodes/ folder if ( Q_strstr( gamePath, "addons/" ) ) return; // don't download into addons/ folder // Disallow .. in paths, but allow multiple periods otherwise. This way we can download blah.dx80.vtx etc. const char *backup = strstr( gamePath, ".." ); const char *extension = strrchr( gamePath, '.' ); if ( backup || !extension ) return; int baseLen = strlen( extension ); if ( baseLen > 4 || baseLen < 3 ) return; if ( !Q_strcasecmp( extension, ".cfg" ) ) return; if ( !Q_strcasecmp( extension, ".lst" ) ) return; if ( !Q_strcasecmp( extension, ".exe" ) ) return; if ( !Q_strcasecmp( extension, ".vbs" ) ) return; if ( !Q_strcasecmp( extension, ".com" ) ) return; if ( !Q_strcasecmp( extension, ".bat" ) ) return; if ( !Q_strcasecmp( extension, ".dll" ) ) return; if ( !Q_strcasecmp( extension, ".ini" ) ) return; if ( !Q_strcasecmp( extension, ".log" ) ) return; if ( !Q_strcasecmp( extension, ".lua" ) ) return; if ( bAsHTTP && !g_pFileSystem->FileExists( va( "%s.bz2", gamePath ) ) ) { // Queue up an HTTP download of the bzipped asset, in case it exists. // When a bzipped download finishes, we'll uncompress the file to it's // original destination, and the queued download of the uncompressed // file will abort. ++m_totalRequests; if ( !TheDownloadCache ) { TheDownloadCache = new DownloadCache; TheDownloadCache->Init(); } RequestContext *rc = new RequestContext; m_queuedRequests.AddToTail( rc ); memset( rc, 0, sizeof(RequestContext) ); rc->status = HTTP_CONNECTING; Q_strncpy( rc->basePath, com_gamedir, BufferSize ); Q_strncpy( rc->gamePath, gamePath, BufferSize ); Q_strncat( rc->gamePath, ".bz2", BufferSize, COPY_ALL_CHARACTERS ); Q_FixSlashes( rc->gamePath, '/' ); // only matters for debug prints, which are full URLS, so we want forward slashes Q_strncpy( rc->serverURL, cl.m_NetChannel->GetRemoteAddress().ToString(), BufferSize ); rc->bIsBZ2 = true; rc->bAsHTTP = true; Q_strncpy( rc->baseURL, baseURL, BufferSize ); Q_strncat( rc->baseURL, "/", BufferSize, COPY_ALL_CHARACTERS ); //ConDColorMsg( DownloadColor, "Queueing %s%s.\n", rc->baseURL, gamePath ); } ++m_totalRequests; if ( !TheDownloadCache ) { TheDownloadCache = new DownloadCache; TheDownloadCache->Init(); } RequestContext *rc = new RequestContext; m_queuedRequests.AddToTail( rc ); memset( rc, 0, sizeof(RequestContext) ); rc->status = HTTP_CONNECTING; Q_strncpy( rc->basePath, com_gamedir, BufferSize ); Q_strncpy( rc->gamePath, gamePath, BufferSize ); Q_FixSlashes( rc->gamePath, '/' ); // only matters for debug prints, which are full URLS, so we want forward slashes Q_strncpy( rc->serverURL, cl.m_NetChannel->GetRemoteAddress().ToString(), BufferSize ); if ( bAsHTTP ) { rc->bAsHTTP = true; Q_strncpy( rc->baseURL, baseURL, BufferSize ); Q_strncat( rc->baseURL, "/", BufferSize, COPY_ALL_CHARACTERS ); } else { rc->bAsHTTP = false; } //ConDColorMsg( DownloadColor, "Queueing %s%s.\n", rc->baseURL, gamePath ); }
void medic_NextPatrolPoint (edict_t *self, edict_t *hint) { edict_t *next=NULL; edict_t *e; vec3_t dir; qboolean switch_paths=false; self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL; // if(self->monsterinfo.aiflags & AI_MEDIC) // return; if(self->goalentity == hint) self->goalentity = NULL; if(self->movetarget == hint) self->movetarget = NULL; if (!(self->monsterinfo.aiflags & AI_MEDIC)) { if(medic_FindDeadMonster(self)) return; } if(self->monsterinfo.pathdir == 1) { if(hint->hint_chain) next = hint->hint_chain; else { self->monsterinfo.pathdir = -1; switch_paths = true; } } if(self->monsterinfo.pathdir == -1) { e = hint_chain_starts[hint->hint_chain_id]; while(e) { if(e->hint_chain == hint) { next = e; break; } e = e->hint_chain; } } if(!next) { self->monsterinfo.pathdir = 1; next = hint->hint_chain; switch_paths = true; } // If switch_paths is true, we reached the end of a hint_chain. Just for grins, // search for *another* visible hint_path chain and use it if it's reasonably close if(switch_paths && hint_chain_count > 1) { edict_t *e; edict_t *alternate=NULL; float dist; vec3_t dir; int i; float bestdistance=512; for(i=game.maxclients+1; i<globals.num_edicts; i++) { e = &g_edicts[i]; if(!e->inuse) continue; if(Q_strcasecmp(e->classname,"hint_path")) continue; if(next && (e->hint_chain_id == next->hint_chain_id)) continue; if(!visible(self,e)) continue; if(!canReach(self,e)) continue; VectorSubtract(e->s.origin,self->s.origin,dir); dist = VectorLength(dir); if(dist < bestdistance) { alternate = e; bestdistance = dist; } } if(alternate) next = alternate; } if(next) { self->hint_chain_id = next->hint_chain_id; VectorSubtract(next->s.origin, self->s.origin, dir); self->ideal_yaw = vectoyaw(dir); self->goalentity = self->movetarget = next; self->monsterinfo.pausetime = 0; self->monsterinfo.aiflags |= AI_MEDIC_PATROL; self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP); // run for it self->monsterinfo.run (self); } else { self->monsterinfo.pausetime = level.time + 100000000; self->monsterinfo.stand (self); } }