PSSM random_pssm(unsigned char order, const unsigned char min_length, const unsigned char max_length, unsigned char alphlen, int seq) { PSSM pssm = initMatrix(order, max_length, alphlen); int i; pssm->max_length = max_length; i = pssm->max_length * pssm->alphabetSize; while (i--) pssm->counts[i] = 0 + RAND_INT(seq); normalize_pssm(pssm, seq); pssm->min_length = min_length; pssm->length = min_length + RAND_INT(max_length - min_length); calcAndSetThresholds(pssm, RAND_FLOAT((2.0 * pssm->length))); return pssm; }
void EmitterStart( Emitter *em, const Vec2i fullPos, const int z, const Vec2i vel) { const Vec2i p = Vec2iAdd(fullPos, Vec2iReal2Full(em->offset)); // TODO: single event multiple particles GameEvent e = GameEventNew(GAME_EVENT_ADD_PARTICLE); e.u.AddParticle.FullPos = p; e.u.AddParticle.Z = z * Z_FACTOR; e.u.AddParticle.Class = em->p; const int speed = RAND_INT(em->minSpeed, em->maxSpeed); const Vec2i baseVel = Vec2iFromPolar(speed, RAND_DOUBLE(0, PI * 2)); e.u.AddParticle.Vel = Vec2iAdd(vel, baseVel); e.u.AddParticle.Angle = RAND_DOUBLE(0, PI * 2); e.u.AddParticle.DZ = RAND_INT(em->minDZ, em->maxDZ); e.u.AddParticle.Spin = RAND_DOUBLE(em->minRotation, em->maxRotation); GameEventsEnqueue(&gGameEvents, e); }
void GunAddBullets( const GunDescription *g, const Vec2i fullPos, const int z, const double radians, const int flags, const int player, const int uid, const bool playSound) { // Add bullets if (g->Bullet) { // Find the starting angle of the spread (clockwise) // Keep in mind the fencepost problem, i.e. spread of 3 means a // total spread angle of 2x width const double spreadStartAngle = g->AngleOffset - (g->Spread.Count - 1) * g->Spread.Width / 2; for (int i = 0; i < g->Spread.Count; i++) { const double recoil = ((double)rand() / RAND_MAX * g->Recoil) - g->Recoil / 2; const double finalAngle = radians + spreadStartAngle + i * g->Spread.Width + recoil; GameEvent e = GameEventNew(GAME_EVENT_ADD_BULLET); strcpy(e.u.AddBullet.BulletClass, g->Bullet->Name); e.u.AddBullet.MuzzlePos = Vec2i2Net(fullPos); e.u.AddBullet.MuzzleHeight = z; e.u.AddBullet.Angle = (float)finalAngle; e.u.AddBullet.Elevation = RAND_INT(g->ElevationLow, g->ElevationHigh); e.u.AddBullet.Flags = flags; e.u.AddBullet.PlayerIndex = player; e.u.AddBullet.UID = uid; GameEventsEnqueue(&gGameEvents, e); } } // Add muzzle flash if (GunHasMuzzle(g)) { GameEvent e = GameEventNew(GAME_EVENT_ADD_PARTICLE); e.u.AddParticle.Class = g->MuzzleFlash; e.u.AddParticle.FullPos = fullPos; e.u.AddParticle.Z = z; e.u.AddParticle.Angle = radians; GameEventsEnqueue(&gGameEvents, e); } // Sound if (playSound && g->Sound) { SoundPlayAt(&gSoundDevice, g->Sound, Vec2iFull2Real(fullPos)); } // Screen shake if (g->ShakeAmount > 0) { GameEvent shake = GameEventNew(GAME_EVENT_SCREEN_SHAKE); shake.u.ShakeAmount = g->ShakeAmount; GameEventsEnqueue(&gGameEvents, shake); } }
int main() { void *add_array[100]; bool unfreed_array[100] = {false}; for (int i = 0; i < 100; i++) { unsigned int size = RAND_INT(1, 100); void *p = ffmalloc(size); printf("address: %p, size: 0x%x\n", p, size); add_array[i] = p; unfreed_array[i] = 1; if (RAND_DOUBLE(0, 1) > 0.1) { int free_index = RAND_INT(0, i + 1); if (unfreed_array[free_index] == true) { printf("free_addr: %p\n", add_array[free_index]); basefree(add_array[free_index]); unfreed_array[free_index] = false; } } } return 0; }
/* * Modifies a WM by stealing from one letter and given to another at each position */ void wm_steal(Annealing *search, int wm_index, float temperature) { unsigned int pos, thief, victim; unsigned int amount, i, nind, wind; PSSM wm, nwm; wm = WM(wm_index); nwm = NWM(wm_index); SWITCH_WM(wm_index); wm = WM(wm_index); nwm = NWM(wm_index); wm->length = nwm->length; pos = wm->length; while (pos--) { /* Steal from one letter, and add to another */ victim = RAND_INT(nwm->alphabetSize); while ( nwm->counts[ WM_IND(nwm, pos, victim) ] == 0) victim = RAND_INT(4.0); thief = RAND_INT(nwm->alphabetSize - 1); if (thief >= victim) thief++; amount = STEAL_AMOUNT; i = ALPHLEN; while (i--) { nind = WM_IND(nwm, pos, i); wind = WM_IND(wm, pos, i); wm->counts[wind] = nwm->counts[nind]; if (i == thief) wm->counts[wind] += amount; else if(i == victim) wm->counts[wind] -= amount; wm->scores[wind] = logtable[wm->counts[wind]]; } } }
char * net_resolve (netstore * ns, char *hostname, int port, char **real_host) { struct addrinfo hints; char ipstring[MAX_HOSTNAME]; char portstring[MAX_HOSTNAME]; int ret; /* if (ns->ip6_hostent) freeaddrinfo (ns->ip6_hostent);*/ sprintf (portstring, "%d", port); memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = PF_UNSPEC; /* support ipv6 and ipv4 */ hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; if (port == 0) ret = getaddrinfo (hostname, NULL, &hints, &ns->ip6_hostent); else ret = getaddrinfo (hostname, portstring, &hints, &ns->ip6_hostent); if (ret != 0) return NULL; #ifdef LOOKUPD /* See note about lookupd above the IPv4 version of net_resolve. */ struct addrinfo *tmp; int count = 0; for (tmp = ns->ip6_hostent; tmp; tmp = tmp->ai_next) count ++; count = RAND_INT(count); while (count--) ns->ip6_hostent = ns->ip6_hostent->ai_next; #endif /* find the numeric IP number */ ipstring[0] = 0; getnameinfo (ns->ip6_hostent->ai_addr, ns->ip6_hostent->ai_addrlen, ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST); if (ns->ip6_hostent->ai_canonname) *real_host = strdup (ns->ip6_hostent->ai_canonname); else *real_host = strdup (hostname); return strdup (ipstring); }
char * net_resolve (netstore * ns, char *hostname, int port, char **real_host) { ns->ip4_hostent = gethostbyname (hostname); if (!ns->ip4_hostent) return NULL; memset (&ns->addr, 0, sizeof (ns->addr)); #ifdef LOOKUPD int count = 0; while (ns->ip4_hostent->h_addr_list[count]) count++; memcpy (&ns->addr.sin_addr, ns->ip4_hostent->h_addr_list[RAND_INT(count)], ns->ip4_hostent->h_length); #else memcpy (&ns->addr.sin_addr, ns->ip4_hostent->h_addr, ns->ip4_hostent->h_length); #endif ns->addr.sin_port = htons (port); ns->addr.sin_family = AF_INET; *real_host = strdup (ns->ip4_hostent->h_name); return strdup (inet_ntoa (ns->addr.sin_addr)); }
void BulletAdd(const NAddBullet add) { const Vec2i pos = Net2Vec2i(add.MuzzlePos); // Find an empty slot in mobobj list TMobileObject *obj = NULL; int i; for (i = 0; i < (int)gMobObjs.size; i++) { TMobileObject *m = CArrayGet(&gMobObjs, i); if (!m->isInUse) { obj = m; break; } } if (obj == NULL) { TMobileObject m; memset(&m, 0, sizeof m); CArrayPushBack(&gMobObjs, &m); i = (int)gMobObjs.size - 1; obj = CArrayGet(&gMobObjs, i); } memset(obj, 0, sizeof *obj); obj->UID = add.UID; obj->bulletClass = StrBulletClass(add.BulletClass); obj->x = pos.x; obj->y = pos.y; obj->z = add.MuzzleHeight; obj->dz = add.Elevation; obj->vel = Vec2iFull2Real(Vec2iScale( GetFullVectorsForRadians(add.Angle), RAND_INT(obj->bulletClass->SpeedLow, obj->bulletClass->SpeedHigh))); if (obj->bulletClass->SpeedScale) { obj->vel.y = obj->vel.y * TILE_WIDTH / TILE_HEIGHT; } obj->PlayerUID = add.PlayerUID; obj->ActorUID = add.ActorUID; obj->range = RAND_INT( obj->bulletClass->RangeLow, obj->bulletClass->RangeHigh); obj->flags = add.Flags; if (obj->bulletClass->HurtAlways) { obj->flags |= FLAGS_HURTALWAYS; } obj->tileItem.kind = KIND_MOBILEOBJECT; obj->tileItem.id = i; obj->isInUse = true; obj->tileItem.x = obj->tileItem.y = -1; obj->tileItem.getPicFunc = NULL; obj->tileItem.getActorPicsFunc = NULL; obj->tileItem.drawFunc = NULL; obj->tileItem.drawData.MobObjId = i; obj->tileItem.CPic = obj->bulletClass->CPic; obj->tileItem.CPicFunc = GetBulletDrawContext; obj->tileItem.size = obj->bulletClass->Size; obj->tileItem.ShadowSize = obj->bulletClass->ShadowSize; obj->updateFunc = UpdateBullet; MapTryMoveTileItem(&gMap, &obj->tileItem, Vec2iFull2Real(pos)); }
static void HandleGameEvent( const GameEvent e, Camera *camera, PowerupSpawner *healthSpawner, CArray *ammoSpawners) { switch (e.Type) { case GAME_EVENT_PLAYER_DATA: PlayerDataAddOrUpdate(e.u.PlayerData); break; case GAME_EVENT_TILE_SET: { Tile *t = MapGetTile(&gMap, Net2Vec2i(e.u.TileSet.Pos)); t->flags = e.u.TileSet.Flags; t->pic = PicManagerGetNamedPic( &gPicManager, e.u.TileSet.PicName); t->picAlt = PicManagerGetNamedPic( &gPicManager, e.u.TileSet.PicAltName); } break; case GAME_EVENT_MAP_OBJECT_ADD: ObjAdd(e.u.MapObjectAdd); break; case GAME_EVENT_MAP_OBJECT_DAMAGE: DamageObject(e.u.MapObjectDamage); break; case GAME_EVENT_SCORE: { PlayerData *p = PlayerDataGetByUID(e.u.Score.PlayerUID); PlayerScore(p, e.u.Score.Score); HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_SCORE, e.u.Score.PlayerUID, e.u.Score.Score); } break; case GAME_EVENT_SOUND_AT: if (!e.u.SoundAt.IsHit || ConfigGetBool(&gConfig, "Sound.Hits")) { SoundPlayAt( &gSoundDevice, StrSound(e.u.SoundAt.Sound), Net2Vec2i(e.u.SoundAt.Pos)); } break; case GAME_EVENT_SCREEN_SHAKE: camera->shake = ScreenShakeAdd( camera->shake, e.u.ShakeAmount, ConfigGetInt(&gConfig, "Graphics.ShakeMultiplier")); break; case GAME_EVENT_SET_MESSAGE: HUDDisplayMessage( &camera->HUD, e.u.SetMessage.Message, e.u.SetMessage.Ticks); break; case GAME_EVENT_GAME_START: gMission.HasStarted = true; break; case GAME_EVENT_ACTOR_ADD: ActorAdd(e.u.ActorAdd); break; case GAME_EVENT_ACTOR_MOVE: ActorMove(e.u.ActorMove); break; case GAME_EVENT_ACTOR_STATE: { TActor *a = ActorGetByUID(e.u.ActorState.UID); if (!a->isInUse) break; ActorSetState(a, (ActorAnimation)e.u.ActorState.State); } break; case GAME_EVENT_ACTOR_DIR: { TActor *a = ActorGetByUID(e.u.ActorDir.UID); if (!a->isInUse) break; a->direction = (direction_e)e.u.ActorDir.Dir; } break; case GAME_EVENT_ACTOR_SLIDE: { TActor *a = ActorGetByUID(e.u.ActorSlide.UID); if (!a->isInUse) break; a->Vel = Net2Vec2i(e.u.ActorSlide.Vel); // Slide sound if (ConfigGetBool(&gConfig, "Sound.Footsteps")) { SoundPlayAt( &gSoundDevice, gSoundDevice.slideSound, Vec2iNew(a->tileItem.x, a->tileItem.y)); } } break; case GAME_EVENT_ACTOR_IMPULSE: { TActor *a = ActorGetByUID(e.u.ActorImpulse.UID); if (!a->isInUse) break; a->Vel = Vec2iAdd(a->Vel, Net2Vec2i(e.u.ActorImpulse.Vel)); const Vec2i pos = Net2Vec2i(e.u.ActorImpulse.Pos); if (!Vec2iIsZero(pos)) { a->Pos = pos; } } break; case GAME_EVENT_ACTOR_SWITCH_GUN: ActorSwitchGun(e.u.ActorSwitchGun); break; case GAME_EVENT_ACTOR_PICKUP_ALL: { TActor *a = ActorGetByUID(e.u.ActorPickupAll.UID); if (!a->isInUse) break; a->PickupAll = e.u.ActorPickupAll.PickupAll; } break; case GAME_EVENT_ACTOR_REPLACE_GUN: ActorReplaceGun(e.u.ActorReplaceGun); break; case GAME_EVENT_ACTOR_HEAL: { TActor *a = ActorGetByUID(e.u.Heal.UID); if (!a->isInUse || a->dead) break; ActorHeal(a, e.u.Heal.Amount); // Sound of healing SoundPlayAt( &gSoundDevice, gSoundDevice.healthSound, Vec2iFull2Real(a->Pos)); // Tell the spawner that we took a health so we can // spawn more (but only if we're the server) if (e.u.Heal.IsRandomSpawned && !gCampaign.IsClient) { PowerupSpawnerRemoveOne(healthSpawner); } if (e.u.Heal.PlayerUID >= 0) { HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_HEALTH, e.u.Heal.PlayerUID, e.u.Heal.Amount); } } break; case GAME_EVENT_ACTOR_ADD_AMMO: { TActor *a = ActorGetByUID(e.u.AddAmmo.UID); if (!a->isInUse || a->dead) break; ActorAddAmmo(a, e.u.AddAmmo.AmmoId, e.u.AddAmmo.Amount); // Tell the spawner that we took ammo so we can // spawn more (but only if we're the server) if (e.u.AddAmmo.IsRandomSpawned && !gCampaign.IsClient) { PowerupSpawnerRemoveOne( CArrayGet(ammoSpawners, e.u.AddAmmo.AmmoId)); } if (e.u.AddAmmo.PlayerUID >= 0) { HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_AMMO, e.u.AddAmmo.PlayerUID, e.u.AddAmmo.Amount); } } break; case GAME_EVENT_ACTOR_USE_AMMO: { TActor *a = ActorGetByUID(e.u.UseAmmo.UID); if (!a->isInUse || a->dead) break; ActorAddAmmo(a, e.u.UseAmmo.AmmoId, -(int)e.u.UseAmmo.Amount); if (e.u.UseAmmo.PlayerUID >= 0) { HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_AMMO, e.u.UseAmmo.PlayerUID, -(int)e.u.UseAmmo.Amount); } } break; case GAME_EVENT_ACTOR_DIE: { TActor *a = ActorGetByUID(e.u.ActorDie.UID); // Check if the player has lives to revive PlayerData *p = PlayerDataGetByUID(a->PlayerUID); if (p != NULL) { p->Lives--; CASSERT(p->Lives >= 0, "Player has died too many times"); if (p->Lives > 0 && !gCampaign.IsClient) { // Find the closest player alive; try to spawn next to that position // if no other suitable position exists Vec2i defaultSpawnPosition = Vec2iZero(); const TActor *closestActor = AIGetClosestPlayer(a->Pos); if (closestActor != NULL) defaultSpawnPosition = closestActor->Pos; PlacePlayer(&gMap, p, defaultSpawnPosition, false); } } ActorDestroy(a); } break; case GAME_EVENT_ACTOR_MELEE: { const TActor *a = ActorGetByUID(e.u.Melee.UID); if (!a->isInUse) break; const BulletClass *b = StrBulletClass(e.u.Melee.BulletClass); if ((HitType)e.u.Melee.HitType != HIT_NONE && HasHitSound(b->Power, a->flags, a->PlayerUID, (TileItemKind)e.u.Melee.TargetKind, e.u.Melee.TargetUID, SPECIAL_NONE, false)) { PlayHitSound( &b->HitSound, (HitType)e.u.Melee.HitType, Vec2iFull2Real(a->Pos)); } if (!gCampaign.IsClient) { Damage( Vec2iZero(), b->Power, a->flags, a->PlayerUID, a->uid, (TileItemKind)e.u.Melee.TargetKind, e.u.Melee.TargetUID, SPECIAL_NONE); } } break; case GAME_EVENT_ADD_PICKUP: PickupAdd(e.u.AddPickup); // Play a spawn sound SoundPlayAt( &gSoundDevice, StrSound("spawn_item"), Net2Vec2i(e.u.AddPickup.Pos)); break; case GAME_EVENT_REMOVE_PICKUP: PickupDestroy(e.u.RemovePickup.UID); if (e.u.RemovePickup.SpawnerUID >= 0) { TObject *o = ObjGetByUID(e.u.RemovePickup.SpawnerUID); o->counter = AMMO_SPAWNER_RESPAWN_TICKS; } break; case GAME_EVENT_BULLET_BOUNCE: { TMobileObject *o = MobObjGetByUID(e.u.BulletBounce.UID); if (o == NULL || !o->isInUse) break; const Vec2i pos = Net2Vec2i(e.u.BulletBounce.BouncePos); PlayHitSound( &o->bulletClass->HitSound, (HitType)e.u.BulletBounce.HitType, Vec2iFull2Real(pos)); if (e.u.BulletBounce.Spark && o->bulletClass->Spark != NULL) { GameEvent s = GameEventNew(GAME_EVENT_ADD_PARTICLE); s.u.AddParticle.Class = o->bulletClass->Spark; s.u.AddParticle.FullPos = pos; s.u.AddParticle.Z = o->z; GameEventsEnqueue(&gGameEvents, s); } o->x = pos.x; o->y = pos.y; o->vel = Net2Vec2i(e.u.BulletBounce.BounceVel); } break; case GAME_EVENT_REMOVE_BULLET: { TMobileObject *o = MobObjGetByUID(e.u.RemoveBullet.UID); if (o == NULL || !o->isInUse) break; MobObjDestroy(o); } break; case GAME_EVENT_PARTICLE_REMOVE: ParticleDestroy(&gParticles, e.u.ParticleRemoveId); break; case GAME_EVENT_GUN_FIRE: { const GunDescription *g = StrGunDescription(e.u.GunFire.Gun); const Vec2i fullPos = Net2Vec2i(e.u.GunFire.MuzzleFullPos); // Add bullets if (g->Bullet && !gCampaign.IsClient) { // Find the starting angle of the spread (clockwise) // Keep in mind the fencepost problem, i.e. spread of 3 means a // total spread angle of 2x width const double spreadStartAngle = g->AngleOffset - (g->Spread.Count - 1) * g->Spread.Width / 2; for (int i = 0; i < g->Spread.Count; i++) { const double recoil = ((double)rand() / RAND_MAX * g->Recoil) - g->Recoil / 2; const double finalAngle = e.u.GunFire.Angle + spreadStartAngle + i * g->Spread.Width + recoil; GameEvent ab = GameEventNew(GAME_EVENT_ADD_BULLET); ab.u.AddBullet.UID = MobObjsObjsGetNextUID(); strcpy(ab.u.AddBullet.BulletClass, g->Bullet->Name); ab.u.AddBullet.MuzzlePos = Vec2i2Net(fullPos); ab.u.AddBullet.MuzzleHeight = e.u.GunFire.Z; ab.u.AddBullet.Angle = (float)finalAngle; ab.u.AddBullet.Elevation = RAND_INT(g->ElevationLow, g->ElevationHigh); ab.u.AddBullet.Flags = e.u.GunFire.Flags; ab.u.AddBullet.PlayerUID = e.u.GunFire.PlayerUID; ab.u.AddBullet.ActorUID = e.u.GunFire.UID; GameEventsEnqueue(&gGameEvents, ab); } } // Add muzzle flash if (GunHasMuzzle(g)) { GameEvent ap = GameEventNew(GAME_EVENT_ADD_PARTICLE); ap.u.AddParticle.Class = g->MuzzleFlash; ap.u.AddParticle.FullPos = fullPos; ap.u.AddParticle.Z = e.u.GunFire.Z; ap.u.AddParticle.Angle = e.u.GunFire.Angle; GameEventsEnqueue(&gGameEvents, ap); } // Sound if (e.u.GunFire.Sound && g->Sound) { SoundPlayAt(&gSoundDevice, g->Sound, Vec2iFull2Real(fullPos)); } // Screen shake if (g->ShakeAmount > 0) { GameEvent s = GameEventNew(GAME_EVENT_SCREEN_SHAKE); s.u.ShakeAmount = g->ShakeAmount; GameEventsEnqueue(&gGameEvents, s); } // Brass shells // If we have a reload lead, defer the creation of shells until then if (g->Brass && g->ReloadLead == 0) { const direction_e d = RadiansToDirection(e.u.GunFire.Angle); const Vec2i muzzleOffset = GunGetMuzzleOffset(g, d); GunAddBrass(g, d, Vec2iMinus(fullPos, muzzleOffset)); } } break; case GAME_EVENT_GUN_RELOAD: { const GunDescription *g = StrGunDescription(e.u.GunReload.Gun); const Vec2i fullPos = Net2Vec2i(e.u.GunReload.FullPos); SoundPlayAtPlusDistance( &gSoundDevice, g->ReloadSound, Vec2iFull2Real(fullPos), RELOAD_DISTANCE_PLUS); // Brass shells if (g->Brass) { GunAddBrass(g, (direction_e)e.u.GunReload.Direction, fullPos); } } break; case GAME_EVENT_GUN_STATE: { const TActor *a = ActorGetByUID(e.u.GunState.ActorUID); if (!a->isInUse) break; WeaponSetState(ActorGetGun(a), (gunstate_e)e.u.GunState.State); } break; case GAME_EVENT_ADD_BULLET: BulletAdd(e.u.AddBullet); break; case GAME_EVENT_ADD_PARTICLE: ParticleAdd(&gParticles, e.u.AddParticle); break; case GAME_EVENT_ACTOR_HIT: { TActor *a = ActorGetByUID(e.u.ActorHit.UID); if (!a->isInUse) break; ActorTakeHit(a, e.u.ActorHit.Special); if (e.u.ActorHit.Power > 0) { DamageActor( a, e.u.ActorHit.Power, e.u.ActorHit.HitterPlayerUID); if (e.u.ActorHit.PlayerUID >= 0) { HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_HEALTH, e.u.ActorHit.PlayerUID, -e.u.ActorHit.Power); } AddBloodSplatter( a->Pos, e.u.ActorHit.Power, Net2Vec2i(e.u.ActorHit.Vel)); } } break; case GAME_EVENT_TRIGGER: { const Tile *t = MapGetTile(&gMap, Net2Vec2i(e.u.TriggerEvent.Tile)); CA_FOREACH(Trigger *, tp, t->triggers) if ((*tp)->id == (int)e.u.TriggerEvent.ID) { TriggerActivate(*tp, &gMap.triggers); break; } CA_FOREACH_END() } break; case GAME_EVENT_EXPLORE_TILES: // Process runs of explored tiles for (int i = 0; i < (int)e.u.ExploreTiles.Runs_count; i++) { Vec2i tile = Net2Vec2i(e.u.ExploreTiles.Runs[i].Tile); for (int j = 0; j < e.u.ExploreTiles.Runs[i].Run; j++) { MapMarkAsVisited(&gMap, tile); tile.x++; if (tile.x == gMap.Size.x) { tile.x = 0; tile.y++; } } } break; case GAME_EVENT_RESCUE_CHARACTER: { TActor *a = ActorGetByUID(e.u.Rescue.UID); if (!a->isInUse) break; a->flags &= ~FLAGS_PRISONER; SoundPlayAt( &gSoundDevice, StrSound("rescue"), Vec2iFull2Real(a->Pos)); } break; case GAME_EVENT_OBJECTIVE_UPDATE: { ObjectiveDef *o = CArrayGet( &gMission.Objectives, e.u.ObjectiveUpdate.ObjectiveId); o->done += e.u.ObjectiveUpdate.Count; // Display a text update effect for the objective HUDAddUpdate( &camera->HUD, NUMBER_UPDATE_OBJECTIVE, e.u.ObjectiveUpdate.ObjectiveId, e.u.ObjectiveUpdate.Count); MissionSetMessageIfComplete(&gMission); } break; case GAME_EVENT_ADD_KEYS: gMission.KeyFlags |= e.u.AddKeys.KeyFlags; SoundPlayAt( &gSoundDevice, gSoundDevice.keySound, Net2Vec2i(e.u.AddKeys.Pos)); // Clear cache since we may now have new paths PathCacheClear(&gPathCache); break; case GAME_EVENT_MISSION_COMPLETE: if (e.u.MissionComplete.ShowMsg) { HUDDisplayMessage(&camera->HUD, "Mission complete", -1); } camera->HUD.showExit = true; MapShowExitArea(&gMap); break; case GAME_EVENT_MISSION_INCOMPLETE: gMission.state = MISSION_STATE_PLAY; break; case GAME_EVENT_MISSION_PICKUP: gMission.state = MISSION_STATE_PICKUP; gMission.pickupTime = gMission.time; SoundPlay(&gSoundDevice, StrSound("whistle")); break; case GAME_EVENT_MISSION_END: gMission.isDone = true; break; default: assert(0 && "unknown game event"); break; } }