00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "g_local.h"
00031
00039 static qboolean Touch_Breakable (edict_t *self, edict_t *activator)
00040 {
00041
00042 if (self->HP != 0)
00043 return qfalse;
00044
00045 if (G_IsActor(activator))
00046 G_ActorFall(activator);
00047
00048 return qfalse;
00049 }
00050
00051 static qboolean Destroy_Breakable (edict_t *self)
00052 {
00053 vec3_t origin;
00054 int i;
00055
00056 VectorCenterFromMinsMaxs(self->absmin, self->absmax, origin);
00057
00058
00059
00060
00061 if (self->HP == 0)
00062 gi.AddEvent(PM_ALL, EV_MODEL_EXPLODE_TRIGGERED);
00063 else
00064 gi.AddEvent(PM_ALL, EV_MODEL_EXPLODE);
00065 gi.WriteShort(self->number);
00066 if (self->particle)
00067 G_SpawnParticle(origin, self->spawnflags, self->particle);
00068
00069 switch (self->material) {
00070 case MAT_GLASS:
00071 G_EventSpawnSound(self, origin, "misc/breakglass+");
00072 break;
00073 case MAT_METAL:
00074 G_EventSpawnSound(self, origin, "misc/breakmetal+");
00075 break;
00076 case MAT_ELECTRICAL:
00077 G_EventSpawnSound(self, origin, "misc/breakelectric+");
00078 break;
00079 case MAT_WOOD:
00080 G_EventSpawnSound(self, origin, "misc/breakwood+");
00081 break;
00082 case MAT_MAX:
00083 break;
00084 }
00085
00086
00087
00088 gi.UnlinkEdict(self);
00089 self->inuse = qfalse;
00090 self->HP = 0;
00091
00092
00093
00094 for (i = 0; i < MAX_TEAMS; i++)
00095 if (level.num_alive[i] && self->visflags & i)
00096 G_CheckVisTeam(i, self, qfalse, self);
00097
00098 G_RecalcRouting(self);
00099 G_TouchEdicts(self, 10.0f);
00100
00101
00102 G_EventPerish(self);
00103 G_FreeEdict(self);
00104
00105 return qtrue;
00106 }
00107
00119 void SP_func_breakable (edict_t *ent)
00120 {
00121 ent->classname = "breakable";
00122 ent->type = ET_BREAKABLE;
00123
00124 ent->flags |= FL_DESTROYABLE;
00125
00126
00127 gi.SetModel(ent, ent->model);
00128 ent->solid = SOLID_BSP;
00129 gi.LinkEdict(ent);
00130
00131 Com_DPrintf(DEBUG_GAME, "func_breakable: model (%s) num: %i mins: %i %i %i maxs: %i %i %i origin: %i %i %i\n",
00132 ent->model, ent->mapNum, (int)ent->mins[0], (int)ent->mins[1], (int)ent->mins[2],
00133 (int)ent->maxs[0], (int)ent->maxs[1], (int)ent->maxs[2],
00134 (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
00135
00136 ent->destroy = Destroy_Breakable;
00137 ent->touch = Touch_Breakable;
00138 }
00139
00140
00141
00142
00143
00144
00145
00152 static qboolean Door_Use (edict_t *door, edict_t *activator)
00153 {
00154 if (door->doorState == STATE_CLOSED) {
00155 door->doorState = STATE_OPENED;
00156
00157
00158 door->angles[YAW] += DOOR_ROTATION_ANGLE;
00159 gi.LinkEdict(door);
00160
00161
00162 if (G_MatchIsRunning()) {
00163
00164 gi.AddEvent(PM_ALL, EV_DOOR_OPEN);
00165 gi.WriteShort(door->number);
00166 if (door->noise[0] != '\0')
00167 G_EventSpawnSound(door, door->origin, door->noise);
00168 }
00169 } else if (door->doorState == STATE_OPENED) {
00170 door->doorState = STATE_CLOSED;
00171
00172
00173 door->angles[YAW] -= DOOR_ROTATION_ANGLE;
00174 gi.LinkEdict(door);
00175
00176
00177
00178 assert(G_MatchIsRunning());
00179
00180 gi.AddEvent(PM_ALL, EV_DOOR_CLOSE);
00181 gi.WriteShort(door->number);
00182 if (door->noise[0] != '\0')
00183 G_EventSpawnSound(door, door->origin, door->noise);
00184 } else
00185 return qfalse;
00186
00187
00188 gi.SetInlineModelOrientation(door->model, door->origin, door->angles);
00189 Com_DPrintf(DEBUG_GAME, "Server processed door movement.\n");
00190
00191
00192 G_RecalcRouting(door);
00193
00194 if (activator && G_IsLivingActor(activator)) {
00195
00196 G_CheckVis(activator, qtrue);
00197
00198
00199 G_CheckVisTeamAll(activator->team, qfalse, activator);
00200 }
00201
00202 return qtrue;
00203 }
00204
00212 static qboolean Touch_DoorTrigger (edict_t *self, edict_t *activator)
00213 {
00214 if (!self->owner)
00215 return qfalse;
00216
00217 if (G_IsAI(activator)) {
00218
00219 if (self->flags & FL_GROUPSLAVE)
00220 self = self->groupMaster;
00221 if (AI_CheckUsingDoor(activator, self->owner))
00222 G_ActorUseDoor(activator, self->owner);
00223
00224 return qfalse;
00225 } else {
00226
00227 G_ActorSetClientAction(activator, self->owner);
00228 return qtrue;
00229 }
00230 }
00231
00237 static void Reset_DoorTrigger (edict_t *self, edict_t *activator)
00238 {
00239 if (activator->clientAction == self)
00240 G_ActorSetClientAction(activator, NULL);
00241 }
00242
00250 void SP_func_door (edict_t *ent)
00251 {
00252 edict_t *other;
00253
00254 ent->classname = "door";
00255 ent->type = ET_DOOR;
00256 if (!ent->noise)
00257 ent->noise = "doors/open_close";
00258
00259
00260 gi.SetModel(ent, ent->model);
00261 ent->solid = SOLID_BSP;
00262 gi.LinkEdict(ent);
00263 ent->doorState = STATE_CLOSED;
00264
00265 if (ent->HP)
00266 ent->flags |= FL_DESTROYABLE;
00267
00268
00269 other = G_TriggerSpawn(ent);
00270 other->touch = Touch_DoorTrigger;
00271 other->reset = Reset_DoorTrigger;
00272
00273 G_ActorSetTU(ent, TU_DOOR_ACTION);
00274 ent->use = Door_Use;
00275 ent->child = other;
00276
00277
00278 if (ent->spawnflags & FL_TRIGGERED)
00279 G_UseEdict(ent, NULL);
00280
00281 Com_DPrintf(DEBUG_GAME, "func_door: model (%s) num: %i solid:%i mins: %i %i %i maxs: %i %i %i absmins: %i %i %i absmaxs: %i %i %i origin: %i %i %i\n",
00282 ent->model, ent->mapNum, ent->solid,
00283 (int)ent->mins[0], (int)ent->mins[1], (int)ent->mins[2],
00284 (int)ent->maxs[0], (int)ent->maxs[1], (int)ent->maxs[2],
00285 (int)ent->absmin[0], (int)ent->absmin[1], (int)ent->absmin[2],
00286 (int)ent->absmax[0], (int)ent->absmax[1], (int)ent->absmax[2],
00287 (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
00288
00289 ent->destroy = Destroy_Breakable;
00290 }
00291
00297 void SP_func_rotating (edict_t *ent)
00298 {
00299 ent->classname = "rotating";
00300 ent->type = ET_ROTATING;
00301
00302
00303 gi.SetModel(ent, ent->model);
00304 ent->solid = SOLID_BSP;
00305 gi.LinkEdict(ent);
00306
00307
00308 if (!ent->speed)
00309 ent->speed = 50;
00310
00311 if (ent->HP)
00312 ent->flags |= FL_DESTROYABLE;
00313
00314 Com_DPrintf(DEBUG_GAME, "func_rotating: model (%s) num: %i mins: %i %i %i maxs: %i %i %i origin: %i %i %i\n",
00315 ent->model, ent->mapNum, (int)ent->mins[0], (int)ent->mins[1], (int)ent->mins[2],
00316 (int)ent->maxs[0], (int)ent->maxs[1], (int)ent->maxs[2],
00317 (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
00318 }