agrip/hooks.mqc

Go to the documentation of this file.
00001 /*  Copyright 2004-2005 Matthew Tylee Atkinson
00002 
00003     This program is free software; you can redistribute it and/or modify
00004     it under the terms of the GNU General Public License as published by
00005     the Free Software Foundation; either version 2 of the License, or
00006     (at your option) any later version.
00007 
00008     This program is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011     GNU General Public License for more details.
00012 
00013     You should have received a copy of the GNU General Public License
00014     along with this program; if not, write to the Free Software
00015     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00016 
00017     See file, 'COPYING', for details.
00018 */
00019 
00020 /* $AGRIP-START */
00021 /* AGRIP Normal QuakeC Hook Functions */
00022 
00023 /*\file
00024 // NOTES
00025 //
00026 // These are called from the main QuakeC code.  They're separated out like this
00027 // so as to keep the footprint on the main code as small as possible.
00028 // 
00029 // The functions are named using the following convention:
00030 //
00031 //      agh_<qc-file-name>_<function-name>
00032 //
00033 // This allows us to know:
00034 //
00035 //      * The function is a hook.
00036 //      * The main QC file that the function is in.
00037 //      * An at-a-glance description of what the function does.
00038 //
00039 */
00040 
00041 
00042 // PROTOTYPES
00043 
00044 void agh_world_checkstringext();
00045 void agh_world_precaches();
00046 void agh_world_padclients();
00047 void agh_client_startdevs();
00048 void agh_client_padclients_connect();
00049 void agh_client_padclients_disconnect();
00050 void agh_player_footsteps();
00051 void agh_player_dietidy();
00052 void agh_weapons_impulsecommands();
00053 
00054 
00055 // IMPLEMENTATIONS
00056 
00061 void agh_world_checkstringext()
00062 {
00063     // Check for string-handling magic from Frik and added by Tonik
00064     if( !cvar("pr_checkextension") )
00065         error("Can't check for required extension: ZQ_QC_STRINGS (no checkextension function)!\n");
00066     if( !checkextension("ZQ_QC_STRINGS") )
00067         error("Required extension ZQ_QC_STRINGS not present!\n");
00068 }
00069 
00076 void agh_world_precaches()
00077 {
00078     // Stuff to re-factor:
00079     precache_model("progs/s_light.spr");
00080     precache_sound("weapons/ric1.wav");
00081     precache_sound("player/land.wav");
00082     precache_sound("weapons/tink1.wav");
00083 
00084     // Welcome message
00085     precache_sound ("welcome.wav");
00086 
00087     // End of Level
00088     precache_sound ("endlevel.wav");
00089 
00090     // Drop Sounds
00091     precache_sound ("haz/drop-huge.wav");
00092     precache_sound ("haz/drop-big.wav");
00093     precache_sound ("haz/drop-small.wav");
00094 
00095     // EtherScan RADAR
00096     precache_sound ("esr/monster-higher.wav");
00097     precache_sound ("esr/monster-same.wav");
00098     precache_sound ("esr/monster-boc.wav");
00099     precache_sound ("esr/monster-lower.wav");
00100     precache_sound ("esr/enemy-higher.wav");
00101     precache_sound ("esr/enemy-same.wav");
00102     precache_sound ("esr/enemy-boc.wav");
00103     precache_sound ("esr/enemy-lower.wav");
00104     precache_sound ("esr/friend-higher.wav");
00105     precache_sound ("esr/friend-same.wav");
00106     precache_sound ("esr/friend-boc.wav");
00107     precache_sound ("esr/friend-lower.wav");
00108     precache_sound ("esr/haz.wav");
00109 
00110     // Navigation
00111     precache_sound ("nav/slope.wav");
00112     precache_sound ("nav/wall.wav");
00113     precache_sound ("nav/wall-scrape.wav");
00114     precache_sound ("nav/door.wav");
00115     precache_sound ("misc/menu3.wav");      // Need replacement wall-touch
00116     precache_sound ("nav/wind.wav");        // del?
00117     precache_sound ("ambience/windfly.wav");
00118     precache_sound ("misc/water2.wav");     // For the open space detection
00119     precache_sound ("nav/up.wav");
00120     precache_sound ("nav/down.wav");
00121 
00122     // Marker
00123     precache_sound ("nav/marker.wav");
00124 
00125     // Footsteps
00126     precache_sound ("footsteps/footstep_l.wav");
00127     precache_sound ("footsteps/footstep_r.wav");
00128 
00129     // D5K Entity Beeps
00130     precache_sound ("buttons/switch04.wav");        // Switch - AG_FIXME
00131     precache_sound ("doors/airdoor2.wav");          // Door - AG_FIXME
00132     precache_sound ("d5k/backpack.wav");
00133     precache_sound ("d5k/outside-fov.wav");
00134 
00135     // Toggles
00136     precache_sound ("toggles/on.wav");
00137     precache_sound ("toggles/off.wav");
00138     precache_sound ("toggles/mode.wav");
00139 
00140     // Ammo Out
00141     precache_sound ("ammo-out.wav");
00142 
00143     // Deny
00144     precache_sound ("deny.wav");
00145 
00147 #ifdef AGRIP_MODHOOK_PRECACHE
00148     agrip_modhook_precache();
00149 #endif
00150 };
00151 
00167 void agh_world_padclients()
00168 {
00169     local float numteams;
00170     local float padclients;
00171     local float botsperteam;
00172     local float i;
00173     local string tteam;
00174 
00175     // Should we be here?
00176     if( infokey(world, "deathmatch") == "0" )
00177         return;
00178     if( infokey(world, "bots_padclients") == "0" )
00179         return;
00180     if( infokey(world, "ag_numteams") == "0" )
00181         return;  // classic Quake TeamDM
00182 
00183     // How many bots to spawn?
00184     if( teamplay )
00185     {
00186         numteams = stof(infokey(world, "ag_numteams"));
00187         if( numteams < 2 || numteams > 4 )
00188         {
00189             error("Server misconfigured: ag_numteams isn't between 2 and 4!\n");
00190         }
00191     }
00192     else
00193     {
00194         numteams = 1;
00195     }
00196     padclients = stof(infokey(world, "bots_padclients"));
00197     botsperteam = rint(padclients / numteams);
00198 
00199     // Sanity check...
00200     if( botsperteam * numteams != padclients )
00201         error("Server misconfigured: bots_padclients doesn't (integer) divide into ag_numteams!\n");
00202 
00203     // Spawn the little fraggers...
00204     /*dprint("need to spawn: ");
00205     dprint(ftos(botsperteam));
00206     dprint(" [bpt] * ");
00207     dprint(ftos(numteams));
00208     dprint(" [teams] = ");
00209     dprint(ftos(padclients));
00210     dprint("\n");*/
00211 
00212     // As we cannot do this in for (while) loops because there are no arrays,
00213     // we have to explicitly say ``spawn a bot with team 2''.  There is a
00214     // short way to do this; just test if ag_numteams is greater than 0/1/2/3
00215     // and if it is, spawn botsperteam with the currently-being-tested team's
00216     // colours and name (done in a for (while) loop).
00217 
00218     // Also we have to wait before spawning the members on each team so that
00219     // we don't overflow the server.  For this reason, we set up an entity to
00220     // do the actual spawning.
00221     
00222     // FIXME disable team command / make it switch your colours too?
00223     
00224     entity spawner;
00225     spawner = spawn();
00226     spawner.items = numteams;
00227     spawner.frags = botsperteam;
00228     spawner.state = 0;  // not spawned any teams yet
00229     spawner.lip = 0;    // not spawned any members of teams yet
00230     spawner.think = snap_misc_botspawner;
00231     spawner.nextthink = time + 2;
00232 }
00233 
00237 void agh_client_startdevs()
00238 {
00239     // Work out which devices are meant to be active...
00240 
00241     // Note that we have to reverse the value of the cvar as it is meant
00242     // to signify that the devices are on if it is 1 -- but we know that
00243     // as we've just connected they aren't.
00244 
00245     // AUX
00246     snap_aux_constructor();
00247 
00248     // Set message lock to un-prioritise the following message...
00249     self.agrip_aux.state = true;
00250    
00251     // Instead of blurting out lots for each dev...
00252     snap_misc_m2m("Starting devices...\n");
00253     safe_soundtoclient(self, self, CHAN_AUTO, "toggles/on.wav", 1, ATTN_NORM);
00254     
00255     // Unset message lock...
00256     self.agrip_aux.state = false;
00257 
00258     // NAV
00259     if( infokey(self, "agv_t_nav") == "1" )
00260         snap_nav_constructor();
00261 
00262     // D5k
00263     if( infokey(self, "agv_t_d5k") == "1" )
00264         snap_d5k_constructor();
00265 
00266     // ESR
00267     if( infokey(self, "agv_t_esr") == "1" )
00268         snap_esr_constructor();
00269 
00270     // Compass Offset...
00271     SNAP_MISC_NORMYAW_OFFSET = self.angles_y;
00272     if( SNAP_MISC_NORMYAW_OFFSET == 270 )
00273         SNAP_MISC_NORMYAW_OFFSET = -90;
00274 };
00275 
00281 void agh_client_padclients_connect()
00282 {
00283     local float teamnum, numteams, numpad, numplrs, botsperteam;
00284     local string conplrteam, sconplrteam;
00285     local string tmp;
00286     local string stmp;
00287     local string cmd;
00288     local string scmd;
00289     local string fullcmd;
00290 
00291     // Should we be here?
00292     if( infokey(world, "deathmatch") == "0" )
00293         return;
00294     if( infokey(world, "bots_padclients") == "0" )
00295         return;
00296     if( infokey(world, "ag_numteams") == "0" )
00297         return;  // classic Quake TeamDM
00298 
00299     // Ugly hack until MAUTH is finished...
00300     /*if( infokey(self, "isbot") != "1" )
00301     if( stof(infokey(self, "fortytwo")) != 42 )
00302     {
00303         sprint(self, PRINT_HIGH, "This is an AudioQuake server, not a standard QuakeWorld server.\nPlease only connect here if you're using AGRIP AudioQuake.\n");
00304         stuffcmd(self, "wait;disconnect\n");
00305         return;
00306     }*/
00307 
00308     if( teamplay )// || coop )
00309     {
00310         // Check number of teams vs our team...
00311         numteams = stof(infokey(world, "ag_numteams"));
00312         conplrteam = infokey(self, "team");
00313         sconplrteam = strzone(conplrteam);
00314         teamnum = snap_misc_numforteamname(conplrteam);
00315 
00316         // Valid team number?
00317         if( teamnum == 0 || teamnum > numteams )
00318         {
00319             sprint(self, PRINT_HIGH, "You have not set yourself to be in one of the teams on this server.\nPlease use the team command to do so and reconnect.\n");
00320             stuffcmd(self, "wait;disconnect\n");
00321             strunzone(sconplrteam);
00322             return;
00323         }
00324         else
00325         {
00326             // Set colours
00327             // (by working out the colours and sending a console command)...
00328             // bottom...
00329             tmp = ftos(snap_misc_bottomforteamnum(teamnum));
00330             stmp = strzone(tmp);
00331             cmd = stradd("bottomcolor ", stmp);
00332             scmd = strzone(cmd);
00333             fullcmd = stradd(scmd, "\n");
00334             stuffcmd(self, fullcmd);
00335             strunzone(scmd);
00336             strunzone(stmp);
00337             // Top...
00338             tmp = ftos(snap_misc_topforteamnum(teamnum));
00339             stmp = strzone(tmp);
00340             cmd = stradd("topcolor ", stmp);
00341             scmd = strzone(cmd);
00342             fullcmd = stradd(scmd, "\n");
00343             stuffcmd(self, fullcmd);
00344             strunzone(scmd);
00345             strunzone(stmp);
00346         }
00347     }
00348     else
00349     {
00350         // FIXME DM
00351         // ACTUALLY, don't need to do anything here
00352     }
00353 
00354     // Now we've added the player, should we remove a bot?
00355     /*FIXME old debug code
00356     dprint("PAD____CON: players: ");
00357     dprint(ftos(numplrs));
00358     dprint("  padclients: ");
00359     dprint(ftos(numpad));
00360     dprint("\n");*/
00361     if( infokey(self, "cab") != "1" )
00362     {
00363         // Kick a bot if a player connects
00364         // and we're over the padding limit...
00365         if( teamplay )
00366         {
00367             // FIXME check that there is not a bot here that should be
00368             // replaced by me -- even though we may not have gone over
00369             // the global padding limit, we could have gone over the limit
00370             // for players in this team.
00371             numpad = stof(infokey(world, "bots_padclients"));
00372             numplrs = CountPlayersTeam(sconplrteam);
00373             botsperteam = numpad / numteams;
00374             /*dprint("PAD____CON:");
00375             dprint("  padc's: ");
00376             dprint(ftos(numpad));
00377             dprint("  bots/team: ");
00378             dprint(ftos(botsperteam));
00379             dprint("  team plrs: ");
00380             dprint(ftos(numplrs));
00381             dprint("  team: ");
00382             dprint(sconplrteam);*/
00383             strunzone(sconplrteam);
00384             if( numplrs > botsperteam )
00385             {
00386                 //dprint("  KICK");
00387                 KickABotTeam(teamnum, 0);
00388             }
00389             else
00390             {
00391                 //dprint("  NO KICK");
00392             }
00393             //dprint("\n");
00394         }
00395         else
00396         {
00397             numpad = stof(infokey(world, "bots_padclients"));
00398             numplrs = CountPlayers();
00399             if( numplrs > numpad )
00400                 KickABotDM(0);
00401         }
00402     }
00403     //else
00404     //{
00405         // Kick a connecting bot if we need to leave a gap
00406         // for a player to connect...
00407         // FIXME
00408         // couldn't doing this begin a recursive loop?  should check before spawning?
00409     //}
00410 }
00411 
00416 void agh_client_padclients_disconnect()
00417 {
00418     // Should we be here?
00419     if( infokey(world, "deathmatch") == "0" )
00420         return;
00421     if( infokey(world, "bots_padclients") == "0" )
00422         return;
00423     if( infokey(world, "ag_numteams") == "0" )
00424         return;  // classic Quake TeamDM
00425 
00426     //dprint("PAD_DISCON: <START>\n");
00427     if( teamplay )// || coop )
00428     {
00429         local float teamnum;
00430         local float numteams;
00431         local float numpad, numplrs;
00432         local string tmp;
00433    
00434         // Check number of teams vs our team...
00435         numteams = stof(infokey(world, "ag_numteams"));
00436         tmp = infokey(self, "team");
00437         teamnum = snap_misc_numforteamname(tmp);
00438     }
00439 
00440     // Now we've added the player, should we remove a bot?
00441     numpad = stof(infokey(world, "bots_padclients"));
00442     numplrs = CountPlayers();
00443     /*dprint("PAD_DISCON:  players: ");
00444     dprint(ftos(numplrs));
00445     dprint("  padclients: ");
00446     dprint(ftos(numpad));
00447     dprint("\n");*/
00448     if( infokey(self, "isbot") != "1" )
00449     {
00450         // Add a bot if a player connects
00451         // and we're under the padding limit...
00452         if( numplrs == numpad )
00453         // (Test for == because this client is just about to disappear
00454         // and when they finally do, we'll be just below the level.)
00455         {
00456             //dprint("PAD_DISCON: ADD A BOT!\n");
00457             if( teamplay == 1 )
00458             {
00459                 local float bot, top;
00460                 bot = stof(infokey(self, "bottom"));
00461                 top = stof(infokey(self, "top"));
00462                 create_bot(bot, top, infokey(self, "team"), 0); 
00463             }
00464             else
00465             {
00466                 create_bot(0, 0, "bots", 0);
00467             }
00468         }
00469     }
00470 }
00471 
00475 void agh_player_footsteps()
00476 {
00477     // Play footsteps if the user has asked for it and they're not stuck...
00478     //
00479     // Please read snap_misc_blockedtest() for an explanation of the stuck
00480     // detection algorithm.
00481     //
00482     // If footsteps are disabled and we are stuck, a sound _is_ played so
00483     // that the player knows they're stuck.
00484     //
00485     // This also works out if the player is scraping along a wall.
00486 
00487     // Get out?
00488     // (It is faster to calculate the negative, as it uses ORs instead of ANDs.)
00489     if( ! (self.walkframe == 1 || self.walkframe == 4) )
00490         return;
00491 
00492     // Check we're not stuck...
00493 
00494     // Test if we are moving...
00495     if( self.origin != self.oldorigin )
00496     {
00497         // Are we scraping against a wall?
00498         // (This would show up as two walls; one front/back and one at the side.)
00499         if( self.agrip_aux.ammo_rockets > 1 )
00500         if( self.origin_z == self.oldorigin_z )
00501         {
00502             safe_soundtoclient(self, self, CHAN_AUTO, "nav/wall-scrape.wav", 0.5, ATTN_NORM);
00503 
00504             // Go on to play a footstep too, as we _are_ moving, but make sure
00505             // we only play it at 1/2 the perceived ``speed''...
00506             if( self.walkframe != 1 )
00507                 return;
00508             // Yes, we _should_ set self.oldorigin, but don't need to here
00509             // anyway -- phew!
00510         }
00511 
00512         // We're walking normally...
00513         // But we need to check that footsteps are turned on...
00514         if( infokey(self, "agv_t_footsteps") == "1" )
00515         {
00516             // Adjust speed according to if we're running or not...
00517             if( fabs(self.velocity_x + self.velocity_y) > 200 || self.walkframe == 1 )
00518             {
00519                 // We may be in water...
00520                 if( self.waterlevel > 1 )
00521                 {
00522                     safe_soundtoclient(self, self, CHAN_AUTO, "misc/outwater.wav", 0.5, ATTN_NORM);
00523                 }
00524                 else if( checkbottom(self) )
00525                 {
00526                     // Generate the footstep sound a bit randomly...
00527                     local float r;
00528                     r = random(); 
00529                     if( r < 0.5 )
00530                     {
00531                         safe_soundtoclient(self, self, CHAN_AUTO, "footsteps/footstep_l.wav", 0.5, ATTN_NORM);
00532                     }
00533                     else
00534                     {
00535                         safe_soundtoclient(self, self, CHAN_AUTO, "footsteps/footstep_r.wav", 0.5, ATTN_NORM);
00536                     }
00537                 }
00538             }
00539         }
00540     }
00541     // We aren't moving.
00542     // If we are stuck, or footsteps are OFF, we'll just continue making
00543     // the ``oomph'' sound...
00544     else //if( infokey(self, "agv_t_footsteps") == 0 )
00545     {
00546         // Need to make sure that we haven't just started moving
00547         // or we'll get spurious oomphs...
00548         if( self.agrip_aux.ammo_rockets > 0 )
00549         if( self.walkframe == 1 )
00550             safe_soundtoclient(self, self, CHAN_AUTO, "player/land.wav", 0.5, ATTN_NORM);
00551     }
00552 
00553     // Store our origin...
00554     self.oldorigin = self.origin;
00555 };
00556 
00560 void agh_player_dietidy()
00561 {
00562     // Set the message lock to un-prioritise the following messages...
00563     self.agrip_aux.state = true;
00564 
00565     // Disable NAV, ESR, D5k...
00566     snap_misc_m2m("Stopping devices...\n");
00567     safe_soundtoclient(self, self, CHAN_AUTO, "toggles/off.wav", 1, ATTN_NORM);
00568 
00569     // NAV
00570     if( infokey(self, "agv_t_nav") == "1" )
00571     {
00572         remove(self.agrip_nav.aiment);
00573         remove(self.agrip_nav);
00574     }
00575 
00576     // D5k
00577     if( infokey(self, "agv_t_d5k") == "1" )
00578     {
00579         remove(self.agrip_d5k);
00580     }
00581 
00582     // ESR
00583     if( infokey(self, "agv_t_esr") == "1" )
00584     {
00585         remove(self.agrip_esr.aiment);
00586         remove(self.agrip_esr.enemy);
00587         remove(self.agrip_esr.goalentity);
00588         remove(self.agrip_esr);
00589     }
00590 
00591     // Remove all waypoints...
00592     if( self.agrip_aux.health > 0 )
00593         snap_misc_m2m("Removing markers...\n");
00594     // FIXME this is an NP-complete ugly hack!!!
00595     while( floor(self.agrip_aux.health) > 0 )
00596     {
00597         // debug info...
00598         /*dprint(self.netname);
00599         dprint(" call m_d with a-aux.h = ");
00600         dprint(ftos(self.agrip_aux.health));
00601         dprint("\n");*/
00602         // Call it *QUIETLY*...
00603         snap_marker_destructor(1);
00604     }
00605 
00606     // AUX
00607     remove(self.agrip_aux);
00608 };
00609 
00613 void agh_weapons_impulsecommands()
00614 {
00615     // TUTOR BOT STUFF
00616 
00617     // Impulse  49  Kicks a bot
00618     //          50  Adds a bot on our team
00619     //          51  Adds an enemy bot
00620     //          52  Sets and un-sets the call flag
00621 
00622     // Note:    Only if we are in teamplay mode will the bot's team be
00623     //          taken into consideration; otherwise it'll always be an
00624     //          opponent to us.
00625 
00626     if( self.impulse == 49 )
00627     {
00628         // Can kick any old bot in DM; not so in team games...
00629         if( teamplay || coop )
00630         {
00631             local float myteam;
00632             myteam = snap_misc_numforteamname(infokey(self, "team"));
00633             KickABotTeam(myteam, true);
00634             // (The true at the end means a client called the function -- so
00635             // some checks need to be done to ensure this is allowed.)
00636         }
00637         else  // FIXME must be DM?
00638         {
00639             KickABotDM(true);  // client called
00640         }
00641     }
00642     
00643     if( self.impulse == 50 )
00644     {
00645         // Add a friend
00646         create_bot(stof(infokey(self, "bottomcolor")), stof(infokey(self, "topcolor")), infokey(self, "team"), true);
00647     }
00648                    
00649     if( self.impulse == 51 )
00650     {
00651         // Add an enemy (to a random team not including my own)...
00652         local float random_enemy_team, mybot, mytop;
00653         local string enemy_teamname;
00654 
00655         // Choose a team that isn't mine to add the top to...
00656         random_enemy_team = snap_misc_pickrndteam(true);
00657         enemy_teamname = snap_misc_nameforteamnum(random_enemy_team);
00658         mybot = snap_misc_bottomforteamnum(random_enemy_team);
00659         mytop = snap_misc_topforteamnum(random_enemy_team);
00660         create_bot(mybot, mytop, enemy_teamname, true);
00661     }
00662     
00663     if( self.impulse == 52 )
00664     {
00665         if( ! self.agrip_aux.ammo_cells )
00666         {
00667             self.agrip_aux.ammo_cells = true;
00668             snap_misc_m2m("Call for help\n");
00669         }
00670         else
00671         {
00672             self.agrip_aux.ammo_cells = false;
00673             snap_misc_m2m("Cancel call for help\n");
00674         }
00675      }
00676 
00677      
00678     // HELPER OBJECTS
00679         
00680     // Impulse  100 toggles nav
00681     //          101         nav/wall warnings
00682     //          102         nav/side wall warnings
00683     //          103         nav/wall hit warnings
00684     //          104         nav/z warnings
00685     //          105         nav/haz warnings
00686     //          106         nav/side haz warnings
00687     //          108         nav/corner warnings
00688     //          110         d5k
00689     //          120             esr
00690     //          121         esr/monster warnings
00691     //          122         esr/enemy warnings
00692     //          123         esr/friend warnings
00693     //          130         footsteps
00694         
00695     // Navigation Helper -- ``nav''
00696     if( self.impulse == 100 )
00697     {
00698         if( infokey(self, "agv_t_nav") == "0" )
00699         {
00700             // Create a new object...
00701             snap_nav_constructor();
00702             stuffcmd(self, "setinfo agv_t_nav 1\n");
00703             snap_misc_m2m("NAV: Enabled.\n");
00704             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00705         }
00706         else
00707         {
00708             // Remove the object, as it exists now...
00709             remove(self.agrip_nav.aiment);
00710             remove(self.agrip_nav);
00711             stuffcmd(self, "setinfo agv_t_nav 0\n");
00712             snap_misc_m2m("NAV: Disabled.\n");
00713             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00714         }
00715     }
00716 
00717     // nav_wall_warnings
00718     if( self.impulse == 101 )
00719     {
00720         if( infokey(self, "agv_t_nav_wall_warnings") == "1" )
00721         {
00722             stuffcmd(self, "setinfo agv_t_nav_wall_warnings 0\n");
00723             snap_misc_m2m("NAV: Wall warnings disabled.\n");
00724             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00725         }
00726         else
00727         {
00728             stuffcmd(self, "setinfo agv_t_nav_wall_warnings 1\n");
00729             snap_misc_m2m("NAV: Wall warnings enabled.\n");
00730             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00731         }
00732     }
00733 
00734     // nav_side_wall_warnings
00735     if( self.impulse == 102 )
00736     {
00737         if( infokey(self, "agv_t_nav_side_wall_warnings") == "1" )
00738         {
00739             stuffcmd(self, "setinfo agv_t_nav_side_wall_warnings 0\n");
00740             snap_misc_m2m("NAV: Side wall warnings disabled.\n");
00741             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00742         }
00743         else
00744         {
00745             stuffcmd(self, "setinfo agv_t_nav_side_wall_warnings 1\n");
00746             snap_misc_m2m("NAV: Side wall warnings enabled.\n");
00747             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00748         }
00749     }
00750 
00751     // nav_wall_touch_warnings
00752     if( self.impulse == 103 )
00753     {
00754         if( infokey(self, "agv_t_nav_wall_touch_warnings") == "1" )
00755         {
00756             stuffcmd(self, "setinfo agv_t_nav_wall_touch_warnings 0\n");
00757             snap_misc_m2m("NAV: Wall touch warnings disabled.\n");
00758             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00759         }
00760         else
00761         {
00762             stuffcmd(self, "setinfo agv_t_nav_wall_touch_warnings 1\n");
00763             snap_misc_m2m("NAV: Wall touch warnings enabled.\n");
00764             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00765         }
00766     }
00767 
00768     // nav_z_warnings
00769     if( self.impulse == 104 )
00770     {
00771         if( infokey(self, "agv_t_nav_z_warnings") == "1" )
00772         {
00773             stuffcmd(self, "setinfo agv_t_nav_z_warnings 0\n");
00774             snap_misc_m2m("NAV: Z warnings disabled.\n");
00775             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00776         }
00777         else
00778         {
00779             stuffcmd(self, "setinfo agv_t_nav_z_warnings 1\n");
00780             snap_misc_m2m("NAV: Z warnings enabled.\n");
00781             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00782         }
00783     }
00784 
00785     // nav_haz_warnings
00786     if( self.impulse == 105 )
00787     {
00788         if( infokey(self, "agv_t_nav_haz_warnings") == "1" )
00789         {
00790             stuffcmd(self, "setinfo agv_t_nav_haz_warnings 0\n");
00791             snap_misc_m2m("NAV: Hazard warnings disabled.\n");
00792             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00793         }
00794         else
00795         {
00796             stuffcmd(self, "setinfo agv_t_nav_haz_warnings 1\n");
00797             snap_misc_m2m("NAV: Hazard warnings enabled.\n");
00798             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00799         }
00800     }
00801 
00802     // nav_side_haz_warnings
00803     if( self.impulse == 106 )
00804     {
00805         if( infokey(self, "agv_t_nav_side_haz_warnings") == "1" )
00806         {
00807             stuffcmd(self, "setinfo agv_t_nav_side_haz_warnings 0\n");
00808             snap_misc_m2m("NAV: Side hazard warnings disabled.\n");
00809             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00810         }
00811         else
00812         {
00813             stuffcmd(self, "setinfo agv_t_nav_side_haz_warnings 1\n");
00814             snap_misc_m2m("NAV: Side hazard warnings enabled.\n");
00815             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00816         }
00817     }
00818 
00819     // nav_space_warnings
00820     if( self.impulse == 107 )
00821     {
00822         if( infokey(self, "agv_t_nav_space_warnings") == "1" )
00823         {
00824             stuffcmd(self, "setinfo agv_t_nav_space_warnings 0\n");
00825             snap_misc_m2m("NAV: Open space warnings disabled.\n");
00826             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00827         }
00828         else
00829         {
00830             stuffcmd(self, "setinfo agv_t_nav_space_warnings 1\n");
00831             snap_misc_m2m("NAV: Open space warnings enabled.\n");
00832             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00833         }
00834     }
00835 
00836     // nav_corner_warnings
00837     if( self.impulse == 108 )
00838     {
00839         if( infokey(self, "agv_t_nav_corner_warnings") == "1" )
00840         {
00841             stuffcmd(self, "setinfo agv_t_nav_corner_warnings 0\n");
00842             snap_misc_m2m("NAV: Corner warnings disabled.\n");
00843             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00844         }
00845         else
00846         {
00847             stuffcmd(self, "setinfo agv_t_nav_corner_warnings 1\n");
00848             snap_misc_m2m("NAV: Corner warnings enabled.\n");
00849             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00850         }
00851     }
00852     
00853     // Detector 5000 -- ``D5k''
00854     if( self.impulse == 110 )
00855     {
00856         if( infokey(self, "agv_t_d5k") == "0" )
00857         {
00858             // Create a new object...
00859             snap_d5k_constructor();
00860             stuffcmd(self, "setinfo agv_t_d5k 1\n");
00861             snap_misc_m2m("D5k: Enabled.\n");
00862             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00863         }
00864         else
00865         {
00866             // Remove the object, as it exists now...
00867             remove(self.agrip_d5k);
00868             stuffcmd(self, "setinfo agv_t_d5k 0\n");
00869             snap_misc_m2m("D5k: Disabled.\n");
00870             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00871         }
00872     }   
00873 
00874     // EtherScan RADAR -- ``ESR''
00875      
00876     // This has 3 modes: off, on (classic) and on (hazard)
00877     // It detects nothing / enemies / drops.
00878    
00879     if( self.impulse == 120 )
00880     {
00881         // Re-enabling the ESR...
00882         if( infokey(self, "agv_t_esr") == "0" )
00883         {
00884             stuffcmd(self, "setinfo agv_t_esr 1\n");
00885             snap_esr_constructor();
00886             safe_soundtoclient(self, self, CHAN_AUTO, "toggles/on.wav", 1, ATTN_NORM);
00887             snap_misc_m2m("ESR: Set to mode 1.\n");
00888         }
00889         // Switching Modes...
00890         else if( infokey(self, "agv_t_esr") == "1" )
00891         {
00892             // If in mode 1, go to 2...
00893             stuffcmd(self, "setinfo agv_t_esr 2\n");
00894 
00895             // If we're in the middle of detecting a far-off enemy, the
00896             // player would have to wait a long time -- so we are going to
00897             // remove this wait...
00898             self.agrip_esr.nextthink = time + 0.01;
00899         }
00900         else if( infokey(self, "agv_t_esr") == "2" )
00901         {
00902             // The user wants to turn the ESR off...
00903             snap_misc_m2m("ESR: Disabled.\n");
00904             stuffcmd(self, "setinfo agv_t_esr 0\n");
00905         }
00906     }
00907 
00908     // ESR Monster Warnings...
00909     if( self.impulse == 121 )
00910     {
00911         if( infokey(self, "agv_t_esr_monster_warnings") == "1" )
00912         {
00913             stuffcmd(self, "setinfo agv_t_esr_monster_warnings 0\n");
00914             snap_misc_m2m("ESR: Monster warnings disabled.\n");
00915             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00916         }
00917         else
00918         {
00919             stuffcmd(self, "setinfo agv_t_esr_monster_warnings 1\n");
00920             snap_misc_m2m("ESR: Monster warnings enabled.\n");
00921             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00922         }
00923     }
00924         
00925     // ESR Enemy Warnings...
00926     if( self.impulse == 122 )
00927     {
00928         if( infokey(self, "agv_t_esr_enemy_warnings") == "1" )
00929         {
00930             stuffcmd(self, "setinfo agv_t_esr_enemy_warnings 0\n");
00931             snap_misc_m2m("ESR: Enemy warnings disabled.\n");
00932             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00933         }
00934         else
00935         {
00936             stuffcmd(self, "setinfo agv_t_esr_enemy_warnings 1\n");
00937             snap_misc_m2m("ESR: Enemy warnings enabled.\n");
00938             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00939         }
00940     }
00941 
00942     // ESR Friend Warnings...
00943     if( self.impulse == 123 )
00944     {
00945         if( infokey(self, "agv_t_esr_friend_warnings") == "1" )
00946         {
00947             stuffcmd(self, "setinfo agv_t_esr_friend_warnings 0\n");
00948             snap_misc_m2m("ESR: Friend warnings disabled.\n");
00949             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00950         }
00951         else
00952         {
00953             stuffcmd(self, "setinfo agv_t_esr_friend_warnings 1\n");
00954             snap_misc_m2m("ESR: Friend warnings enabled.\n");
00955             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00956         }
00957     }
00958     
00959     // Footsteps...
00960     if( self.impulse == 130 )
00961     {
00962         if( infokey(self, "agv_t_footsteps") == "1" )
00963         {
00964             stuffcmd(self, "setinfo agv_t_footsteps 0\n");
00965             snap_misc_m2m("Footsteps disabled.\n");
00966             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/off.wav", 1, ATTN_NORM);
00967         }
00968         else
00969         {
00970             stuffcmd(self, "setinfo agv_t_footsteps 1\n");
00971             snap_misc_m2m("Footsteps enabled.\n");
00972             safe_soundtoclient(self, self, CHAN_VOICE, "toggles/on.wav", 1, ATTN_NORM);
00973         }
00974     }
00975 
00976 
00977     // IMMEDIATE USE ITEMS...
00978     
00979     // Impulse  140 activates   compass
00980     //          141             open space sweep
00981     //          150             drop describer
00982     //          160             jump describer
00983     //          170             adds a marker
00984     //          171             deletes last marker
00985      
00986     // Compass...
00987     if( self.impulse == 140 )
00988         snap_extnav_compass();
00989 
00990     // Spawn a sweep object...
00991     if( self.impulse == 141 )
00992     {
00993         local entity sweep;
00994         sweep = spawn();
00995         self.groundentity = sweep;
00996         sweep.owner = self;
00997         sweep.health = stof(infokey(self, "agv_nav_detrange"));
00998         sweep.think = snap_extnav_osd;
00999         sweep.nextthink = time;
01000         // it will remove itself when completed.
01001     }
01002             
01003     // Drop description...
01004     if( self.impulse == 150 )
01005     if( infokey(self, "agv_t_nav") == "1" )
01006     {
01007         // The NAV device will tell us what lies in the drop.
01008         // The property we examine is set every time it thinks.
01009         if( self.agrip_nav.weapon == CONTENT_EMPTY )
01010             snap_misc_m2m("Ground.\n");
01011         else if( self.agrip_nav.weapon == CONTENT_WATER )
01012             snap_misc_m2m("Water.\n");
01013         else if( self.agrip_nav.weapon == CONTENT_SLIME )
01014             snap_misc_m2m("Slime.\n");
01015         else if( self.agrip_nav.weapon == CONTENT_LAVA )
01016             snap_misc_m2m("Lava.\n");
01017         else
01018             safe_soundtoclient(self, self, CHAN_AUTO, "deny.wav", 1, ATTN_NORM);
01019     }
01020    
01021     // Jump description...
01022     if( self.impulse == 160 )
01023     {
01024         // The NAV device will tell us if we can make the jump.
01025         // The property we examine is set every time it thinks.
01026         if( self.agrip_nav.takedamage == SNAP_NAV_JMP_RUN )
01027         {
01028             snap_misc_m2m("Running Jump.\n");
01029         }
01030         else if( self.agrip_nav.takedamage == SNAP_NAV_JMP_NRM )
01031         {
01032             snap_misc_m2m("Normal Jump.\n");
01033         }
01034         else
01035         {
01036             safe_soundtoclient(self, self, CHAN_AUTO, "deny.wav", 1, ATTN_NORM);
01037         }
01038     }
01039 
01040     // Marker: Add
01041     if( self.impulse == 170 )
01042     {
01043         snap_marker_constructor();
01044     }
01045 
01046     // Marker: Delete last
01047     if( self.impulse == 171 )
01048     {
01049         snap_marker_destructor(0);
01050     }
01051 
01052     
01053    // STATUS INDICATORS...
01054     
01055    // Impulse   90      gives   Health and Armour levels
01056    //           91              Ammo Overview
01057     
01058     if( self.impulse == 90 )
01059     {
01060         local string varval;
01061         varval = ftos(self.health);
01062         snap_misc_m2m(varval);
01063         sprint(self, 1, " health, ");
01064         varval = ftos(self.armorvalue);
01065         sprint(self, 1, varval);
01066         sprint(self, 1, " armour at factor ");
01067         varval = ftos(self.armortype);
01068         sprint(self, 1, varval);
01069         sprint(self, 1, ".\n");
01070     }
01071 
01072     if( self.impulse == 91 )
01073     {
01074         local string varval;
01075         varval = ftos(self.ammo_shells);
01076         snap_misc_m2m(varval);
01077         sprint(self, 1, " shells, ");
01078         varval = ftos(self.ammo_nails);
01079         sprint(self, 1, varval);
01080         sprint(self, 1, " nails, ");
01081         varval = ftos(self.ammo_rockets);
01082         sprint(self, 1, varval);
01083         sprint(self, 1, " rockets, ");
01084         varval = ftos(self.ammo_cells);
01085         sprint(self, 1, varval);
01086         sprint(self, 1, " cells.\n");
01087     }
01088 };
01089 
01090 /* $AGRIP-END */

Generated on Tue Jan 1 17:55:54 2008 for AudioQuake QuakeC by  doxygen 1.5.4