static void DestroyObject( TObject *o, const int flags, const int playerUID, const int uid) { o->Health = 0; const Vec2i realPos = Vec2iNew(o->tileItem.x, o->tileItem.y); if (!gCampaign.IsClient) { // Update objective UpdateMissionObjective(&gMission, o->tileItem.flags, OBJECTIVE_DESTROY); // Extra score if objective if ((o->tileItem.flags & TILEITEM_OBJECTIVE) && playerUID >= 0) { GameEvent e = GameEventNew(GAME_EVENT_SCORE); e.u.Score.PlayerUID = playerUID; e.u.Score.Score = OBJECT_SCORE; GameEventsEnqueue(&gGameEvents, e); } // Weapons that go off when this object is destroyed const Vec2i fullPos = Vec2iReal2Full(realPos); for (int i = 0; i < (int)o->Class->DestroyGuns.size; i++) { const GunDescription **g = CArrayGet(&o->Class->DestroyGuns, i); GunFire(*g, fullPos, 0, 0, flags, playerUID, uid, true, false); } // A wreck left after the destruction of this object // TODO: doesn't need to be network event GameEvent e = GameEventNew(GAME_EVENT_ADD_BULLET); e.u.AddBullet.UID = MobObjsObjsGetNextUID(); strcpy(e.u.AddBullet.BulletClass, "fireball_wreck"); e.u.AddBullet.MuzzlePos = Vec2i2Net(fullPos); e.u.AddBullet.MuzzleHeight = 0; e.u.AddBullet.Angle = 0; e.u.AddBullet.Elevation = 0; e.u.AddBullet.Flags = 0; e.u.AddBullet.PlayerUID = -1; e.u.AddBullet.ActorUID = -1; GameEventsEnqueue(&gGameEvents, e); } SoundPlayAt(&gSoundDevice, gSoundDevice.wreckSound, realPos); // Turn the object into a wreck, if available if (o->Class->Wreck.Pic) { o->tileItem.flags = TILEITEM_IS_WRECK; } else { ObjDestroy(o->tileItem.id); } // Update pathfinding cache since this object could have blocked a path // before PathCacheClear(&gPathCache); }
void ObjsTerminate(void) { for (int i = 0; i < (int)gObjs.size; i++) { TObject *o = CArrayGet(&gObjs, i); if (o->isInUse) { ObjDestroy(i); } } CArrayTerminate(&gObjs); }
/*---------------------------------------------------------------------*/ void HSH_Cleanup(struct worker *wrk) { if (wrk->nobjcore != NULL) ObjDestroy(wrk, &wrk->nobjcore); if (wrk->nobjhead != NULL) { Lck_Delete(&wrk->nobjhead->mtx); FREE_OBJ(wrk->nobjhead); wrk->nobjhead = NULL; wrk->stats->n_objecthead--; } if (wrk->nhashpriv != NULL) { /* XXX: If needed, add slinger method for this */ free(wrk->nhashpriv); wrk->nhashpriv = NULL; } }
static void DamageObject( const int power, const int flags, const int player, const int uid, TTileItem *target) { TObject *object = CArrayGet(&gObjs, target->id); // Don't bother if object already destroyed if (object->structure <= 0) { return; } object->structure -= power; const Vec2i pos = Vec2iNew(target->x, target->y); // Destroying objects and all the wonderful things that happen if (object->structure <= 0) { object->structure = 0; UpdateMissionObjective( &gMission, object->tileItem.flags, OBJECTIVE_DESTROY, player, pos); if (object->flags & OBJFLAG_QUAKE) { GameEvent shake; shake.Type = GAME_EVENT_SCREEN_SHAKE; shake.u.ShakeAmount = SHAKE_BIG_AMOUNT; GameEventsEnqueue(&gGameEvents, shake); } const Vec2i fullPos = Vec2iReal2Full( Vec2iNew(object->tileItem.x, object->tileItem.y)); if (object->flags & OBJFLAG_EXPLOSIVE) { GunAddBullets( StrGunDescription("explosion1"), fullPos, 0, 0, flags, player, uid, true); GunAddBullets( StrGunDescription("explosion2"), fullPos, 0, 0, flags, player, uid, true); GunAddBullets( StrGunDescription("explosion3"), fullPos, 0, 0, flags, player, uid, true); } else if (object->flags & OBJFLAG_FLAMMABLE) { GunAddBullets( StrGunDescription("fire_explosion"), fullPos, 0, 0, flags, player, uid, true); } else if (object->flags & OBJFLAG_POISONOUS) { GunAddBullets( StrGunDescription("gas_poison_explosion"), fullPos, 0, 0, flags, player, uid, true); } else if (object->flags & OBJFLAG_CONFUSING) { GunAddBullets( StrGunDescription("gas_confuse_explosion"), fullPos, 0, 0, flags, player, uid, true); } else { // A wreck left after the destruction of this object GameEvent e; memset(&e, 0, sizeof e); e.Type = GAME_EVENT_ADD_BULLET; e.u.AddBullet.BulletClass = StrBulletClass("fireball_wreck"); e.u.AddBullet.MuzzlePos = fullPos; e.u.AddBullet.MuzzleHeight = 0; e.u.AddBullet.Angle = 0; e.u.AddBullet.Elevation = 0; e.u.AddBullet.Flags = 0; e.u.AddBullet.PlayerIndex = -1; e.u.AddBullet.UID = -1; GameEventsEnqueue(&gGameEvents, e); SoundPlayAt( &gSoundDevice, gSoundDevice.wreckSound, Vec2iNew(object->tileItem.x, object->tileItem.y)); } if (object->wreckedPic) { object->tileItem.flags = TILEITEM_IS_WRECK; object->pic = object->wreckedPic; object->picName = ""; } else { ObjDestroy(object->tileItem.id); } } }