g_mission.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 Original file from Quake 2 v3.21: quake2-2.31/game/g_spawn.c
00010 Copyright (C) 1997-2001 Id Software, Inc.
00011 
00012 This program is free software; you can redistribute it and/or
00013 modify it under the terms of the GNU General Public License
00014 as published by the Free Software Foundation; either version 2
00015 of the License, or (at your option) any later version.
00016 
00017 This program is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021 See the GNU General Public License for more details.
00022 
00023 You should have received a copy of the GNU General Public License
00024 along with this program; if not, write to the Free Software
00025 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00026 
00027 */
00028 
00029 #include "g_local.h"
00030 
00038 qboolean G_MissionTouch (edict_t *self, edict_t *activator)
00039 {
00040     if (!self->owner)
00041         return qfalse;
00042 
00043     switch (self->owner->team) {
00044     case TEAM_ALIEN:
00045         if (G_IsAlien(activator)) {
00046             if (!self->count) {
00047                 self->count = level.actualRound;
00048                 gi.BroadcastPrintf(PRINT_HUD, _("Aliens entered target zone\n"));
00049             }
00050             return qtrue;
00051         } else {
00052             /* reset king of the hill counter */
00053             self->count = 0;
00054         }
00055     /* general case that also works for multiplayer teams */
00056     default:
00057         if (activator->team == self->owner->team) {
00058             if (!self->owner->count) {
00059                 self->owner->count = level.actualRound;
00060                 if (self->owner->item) {
00061                     /* search the item in the activator's inventory */
00062                     containerIndex_t container;
00063 
00064                     for (container = 0; container < gi.csi->numIDs; container++) {
00065                         const invDef_t *invDef = INVDEF(container);
00066                         invList_t *ic;
00067                         /* ignore items linked from any temp container the actor
00068                          * must have this in his hands */
00069                         if (invDef->temp)
00070                             continue;
00071                         for (ic = CONTAINER(activator, container); ic; ic = ic->next) {
00072                             const objDef_t *od = ic->item.t;
00073                             /* check whether we found the searched item in the
00074                              * actor's inventory */
00075                             if (!strcmp(od->id, self->owner->item)) {
00076                                 /* drop the weapon - even if out of TUs */
00077                                 G_ActorInvMove(activator, invDef, ic, INVDEF(gi.csi->idFloor),
00078                                     NONE, NONE, qfalse);
00079                                 gi.BroadcastPrintf(PRINT_HUD, _("Item was placed\n"));
00080                                 self->owner->count = level.actualRound;
00081                                 return qtrue;
00082                             }
00083                         }
00084                     }
00085                 } else {
00086                     gi.BroadcastPrintf(PRINT_HUD, _("Target zone is occupied\n"));
00087                 }
00088             }
00089             return qtrue;
00090         } else {
00091             /* reset king of the hill counter */
00092             self->count = 0;
00093         }
00094     }
00095     return qfalse;
00096 }
00097 
00101 qboolean G_MissionDestroy (edict_t *self)
00102 {
00103     return qtrue;
00104 }
00105 
00109 qboolean G_MissionUse (edict_t *self, edict_t *activator)
00110 {
00111     edict_t *target = G_FindTargetEntity(self->target);
00112     if (!target) {
00113         gi.DPrintf("Target '%s' wasn't found for misc_mission\n", self->target);
00114         G_FreeEdict(self);
00115         return qfalse;
00116     }
00117 
00118     if (target->destroy) {
00119         /* set this to zero to determine that this is a triggered destroy call */
00120         target->HP = 0;
00121         target->destroy(target);
00122         /* freed when the level changes */
00123         self->target = NULL;
00124         self->use = NULL;
00125     } else if (target->use)
00126         target->use(target, activator);
00127 
00128     return qtrue;
00129 }
00130 
00135 void G_MissionThink (edict_t *self)
00136 {
00137     edict_t *chain = self->groupMaster;
00138     edict_t *ent;
00139     int team;
00140 
00141     if (!G_MatchIsRunning())
00142         return;
00143 
00144     /* when every player has joined the match - spawn the mission target
00145      * particle (if given) to mark the trigger */
00146     if (self->particle) {
00147         G_SpawnParticle(self->origin, self->spawnflags, self->particle);
00148 
00149         /* This is automatically freed on map shutdown */
00150         self->particle = NULL;
00151     }
00152 
00153     if (!chain)
00154         chain = self;
00155     while (chain) {
00156         if (chain->type == ET_MISSION) {
00157             if (chain->item) {
00158                 const invList_t *ic;
00159                 G_GetFloorItems(chain);
00160                 ic = FLOOR(chain);
00161                 if (!ic) {
00162                     /* reset the counter if there is no item */
00163                     chain->count = 0;
00164                     return;
00165                 }
00166                 for (; ic; ic = ic->next) {
00167                     const objDef_t *od = ic->item.t;
00168                     assert(od);
00169                     /* not the item we are looking for */
00170                     if (!strcmp(od->id, chain->item))
00171                         break;
00172                 }
00173                 if (!ic) {
00174                     /* reset the counter if it's not the searched item */
00175                     chain->count = 0;
00176                     return;
00177                 }
00178             }
00179             if (chain->time) {
00180                 /* not every edict in the group chain has
00181                  * been occupied long enough */
00182                 if (!chain->count || level.actualRound - chain->count < chain->time)
00183                     return;
00184             }
00185             /* not destroyed yet */
00186             if ((chain->flags & FL_DESTROYABLE) && chain->HP)
00187                 return;
00188         }
00189         chain = chain->groupChain;
00190     }
00191 
00192     if (self->use)
00193         self->use(self, NULL);
00194 
00195     /* store team before the edict is released */
00196     team = self->team;
00197 
00198     chain = self->groupMaster;
00199     if (!chain)
00200         chain = self;
00201     while (chain) {
00202         if (chain->item != NULL) {
00203             edict_t *item = G_GetEdictFromPos(chain->pos, ET_ITEM);
00204             if (item != NULL) {
00205                 if (!G_InventoryRemoveItemByID(chain->item, item, gi.csi->idFloor)) {
00206                     Com_Printf("Could not remove item '%s' from floor edict %i\n",
00207                             chain->item, item->number);
00208                 } else {
00209                     G_AppearPerishEvent(G_VisToPM(item->visflags), qfalse, item, NULL);
00210                 }
00211             }
00212         }
00213         if (chain->particle != NULL) {
00215             edict_t *particle = G_GetEdictFromPos(chain->pos, ET_PARTICLE);
00216             if (particle != NULL) {
00217                 G_AppearPerishEvent(PM_ALL, qfalse, particle, NULL);
00218                 G_FreeEdict(particle);
00219             }
00220         }
00221 
00222         ent = chain->groupChain;
00223         /* free the trigger */
00224         if (chain->child)
00225             G_FreeEdict(chain->child);
00226         /* free the group chain */
00227         G_FreeEdict(chain);
00228         chain = ent;
00229     }
00230     self = NULL;
00231 
00232     /* still active mission edicts left */
00233     ent = NULL;
00234     while ((ent = G_EdictsGetNextInUse(ent)))
00235         if (ent->type == ET_MISSION && ent->team == team)
00236             return;
00237 
00238     G_MatchEndTrigger(team, 10);
00239 }

Generated by  doxygen 1.6.2