static void blaster_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { HELEMENT hBlastElement; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); switch (ElementPtr0->mass_points) { case BLASTER_DAMAGE * 1: BlastElementPtr->life_span = 2; BlastElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 0); BlastElementPtr->preprocess_func = NULL; break; case BLASTER_DAMAGE * 2: BlastElementPtr->life_span = 6; BlastElementPtr->current.image.frame = IncFrameIndex (ElementPtr0->current.image.frame); break; case BLASTER_DAMAGE * 3: BlastElementPtr->life_span = 7; BlastElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 20); break; } UnlockElement (hBlastElement); } }
static void InitSpeechGraphics (void) { InitOscilloscope (SetAbsFrameIndex (ActivityFrame, 9)); InitSlider (0, SLIDER_Y, SIS_SCREEN_WIDTH, SetAbsFrameIndex (ActivityFrame, 5), SetAbsFrameIndex (ActivityFrame, 2)); }
static void RefreshResponses (ENCOUNTER_STATE *pES) { COORD y; BYTE response, extra_y; // JMS_GFX SIZE leading; STAMP s; SetContext (SpaceContext); GetContextFontLeading (&leading); BatchGraphics (); DrawSISComWindow (); y = SLIDER_Y + SLIDER_HEIGHT + RES_SCALE(1); // JMS_GFX for (response = pES->top_response; response < pES->num_responses; ++response) { extra_y = (response == pES->top_response ? 0 : IF_HD(22)); // JMS_GFX pES->response_list[response].response_text.baseline.x = TEXT_X_OFFS + RES_SCALE(8); // JMS_GFX pES->response_list[response].response_text.baseline.y = y + leading + extra_y; // JMS_GFX pES->response_list[response].response_text.align = ALIGN_LEFT; if (response == pES->cur_response) y = add_text (-1, &pES->response_list[response].response_text); else y = add_text (-2, &pES->response_list[response].response_text); } if (pES->top_response) { s.origin.y = SLIDER_Y + SLIDER_HEIGHT + 1; s.frame = SetAbsFrameIndex (ActivityFrame, 6); } else if (y > SIS_SCREEN_HEIGHT) { s.origin.y = SIS_SCREEN_HEIGHT - 2; s.frame = SetAbsFrameIndex (ActivityFrame, 7); } else s.frame = 0; if (s.frame) { RECT r; GetFrameRect (s.frame, &r); s.origin.x = SIS_SCREEN_WIDTH - r.extent.width - 1; DrawStamp (&s); } UnbatchGraphics (); }
void DrawCrewFuelString (COORD y, SIZE state) { STAMP Stamp; Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT; if (state == 0) { Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + 6; if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); DrawStamp (&Stamp); }
void DrawCrewFuelString (COORD y, SIZE state) { STAMP Stamp; Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT - RES_CASE(0,6,12);//(RESOLUTION_FACTOR == 2 ? 12 : 0); if (state == 0) { Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + RES_STAT_SCALE(6) - RES_CASE(0,8,8);//(RESOLUTION_FACTOR == 2 ? 8 : 0); // JMS_GFX if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); DrawStamp (&Stamp); }
BOOLEAN GetInitialMeleeStarShips (HSTARSHIP *result) { COUNT playerI; COUNT playerMask; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { FRAME frame; frame = SetAbsFrameIndex (PickMeleeFrame, playerI); UpdatePickMeleeFleetValue (frame, playerI); DrawPickMeleeFrame (playerI); } // Fade in SleepThreadUntil (FadeScreen (FadeAllToColor, ONE_SECOND / 2) + ONE_SECOND / 60); FlushColorXForms (); playerMask = 0; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) playerMask |= (1 << playerI); return GetMeleeStarShips (playerMask, result); }
static void spawn_rubble (ELEMENT *AsteroidElementPtr) { HELEMENT hRubbleElement; hRubbleElement = AllocElement (); if (hRubbleElement) { ELEMENT *RubbleElementPtr; PutElement (hRubbleElement); LockElement (hRubbleElement, &RubbleElementPtr); RubbleElementPtr->playerNr = AsteroidElementPtr->playerNr; RubbleElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; RubbleElementPtr->life_span = 5; RubbleElementPtr->turn_wait = RubbleElementPtr->next_turn = 0; SetPrimType (&DisplayArray[RubbleElementPtr->PrimIndex], STAMP_PRIM); RubbleElementPtr->current.image.farray = asteroid; RubbleElementPtr->current.image.frame = SetAbsFrameIndex (asteroid[0], ANGLE_TO_FACING (FULL_CIRCLE)); RubbleElementPtr->current.location = AsteroidElementPtr->current.location; RubbleElementPtr->preprocess_func = animation_preprocess; RubbleElementPtr->death_func = spawn_asteroid; UnlockElement (hRubbleElement); } }
static void nuke_preprocess (PELEMENT ElementPtr) { COUNT facing; facing = GetFrameIndex (ElementPtr->next.image.frame); if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { if (TrackShip (ElementPtr, &facing) > 0) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; } ElementPtr->turn_wait = TRACK_WAIT; } { SIZE speed; #define THRUST_SCALE DISPLAY_TO_WORLD (1) if ((speed = MISSILE_SPEED + ((MISSILE_LIFE - ElementPtr->life_span) * THRUST_SCALE)) > MAX_MISSILE_SPEED) speed = MAX_MISSILE_SPEED; SetVelocityVector (&ElementPtr->velocity, speed, facing); } }
static void spin_preprocess (ELEMENT *ElementPtr) { ELEMENT *ShipPtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); if (ShipPtr->crew_level && ++StarShipPtr->RaceDescPtr->characteristics.special_wait > MAX_SAWS) { ElementPtr->life_span = 1; ElementPtr->state_flags |= DISAPPEARING; } else { ++ElementPtr->life_span; if (ElementPtr->turn_wait) --ElementPtr->turn_wait; else { #define LAST_SPIN_INDEX 1 if (GetFrameIndex (ElementPtr->current.image.frame) < LAST_SPIN_INDEX) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 0); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = SAW_RATE; } } UnlockElement (StarShipPtr->hShip); }
static void crystal_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { HELEMENT hBlastElement; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->current.location = ElementPtr1->current.location; BlastElementPtr->life_span = NUM_SPARKLES; BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], 2); /* skip stones */ UnlockElement (hBlastElement); } }
static void animatePowerLines (MENU_STATE *pMS) { static STAMP s; static COLORMAP ColorMap; static TimeCount NextTime = 0; TimeCount Now = GetTimeCounter (); if (pMS) { // Init animation s.origin.x = 0; s.origin.y = 0; s.frame = SetAbsFrameIndex (pMS->ModuleFrame, 24); ColorMap = SetAbsColorMapIndex (pMS->CurString, 0); } if (Now >= NextTime || pMS) { NextTime = Now + (ONE_SECOND / HANGAR_ANIM_RATE); SetColorMap (GetColorMapAddress (ColorMap)); DrawStamp (&s); // Advance colomap cycle ColorMap = SetRelColorMapIndex (ColorMap, 1); } }
static void DrawRestartMenu (BYTE OldState, BYTE NewState, FRAME f) { RECT r; TEXT t; UNICODE buf[64]; LockMutex (GraphicsLock); SetContext (ScreenContext); r.corner.x = r.corner.y = r.extent.width = r.extent.height = 0; SetContextClipRect (&r); r.corner.x = 0; r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; SetFlashRect (&r, SetAbsFrameIndex (f, NewState + 1)); // Put version number in the corner SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - 3; t.baseline.y = SCREEN_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); UnlockMutex (GraphicsLock); (void) OldState; /* Satisfying compiler (unused parameter) */ }
static void pump_up_preprocess (ELEMENT *ElementPtr) { if (--ElementPtr->thrust_wait & 1) { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (((ElementPtr->turn_wait & REVERSE_DIR) && (frame_index % NUM_PUMP_ANIMS) != 0) || (!(ElementPtr->turn_wait & REVERSE_DIR) && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) { --frame_index; ElementPtr->turn_wait |= REVERSE_DIR; } else { ++frame_index; ElementPtr->turn_wait &= ~REVERSE_DIR; } ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, frame_index); ElementPtr->state_flags |= CHANGING; } }
// JMS_GFX: The cleanup boolean can be used to avoid drawing a wrong-sized "Setup" flash overlay. static void DrawRestartMenu (MENU_STATE *pMS, BYTE NewState, FRAME f, BOOLEAN cleanup) { POINT origin; origin.x = 0; origin.y = 0; Flash_setOverlay (pMS->flashContext, &origin, SetAbsFrameIndex (f, NewState + 1), cleanup); }
static BOOLEAN TalkSegue (COUNT wait_track) { TALKING_STATE talkingState; // Transition animation to talking state, if necessary if (wantTalkingAnim () && haveTalkingAnim ()) { if (haveTransitionAnim ()) setRunIntroAnim (); setRunTalkingAnim (); // wait until the transition finishes while (runningIntroAnim ()) runCommAnimFrame (); } memset (&talkingState, 0, sizeof talkingState); if (wait_track == 0) { // Restarting with a rewind wait_track = WAIT_TRACK_ALL; talkingState.rewind = true; } else if (!PlayingTrack ()) { // initial start of player PlayTrack (); assert (PlayingTrack ()); } // Run the talking controls SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); talkingState.InputFunc = DoTalkSegue; talkingState.waitTrack = wait_track; DoInput (&talkingState, FALSE); ClearSubtitles (); if (talkingState.ended) { // reached the end; set STOP icon SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); } // transition back to silent, if necessary if (runningTalkingAnim ()) setStopTalkingAnim (); // Wait until the animation task stops "talking" while (runningTalkingAnim ()) runCommAnimFrame (); return talkingState.ended; }
void MeleeShipDeath (STARSHIP *ship) { FRAME frame; // Deactivate fleet position. ship->SpeciesID = NO_ID; frame = SetAbsFrameIndex (PickMeleeFrame, ship->playerNr); CrossOutShip (frame, ship->index); UpdatePickMeleeFleetValue (frame, ship->playerNr); }
static void DrawDevicesDisplay (DEVICES_STATE *devState) { TEXT t; RECT r; STAMP s; COORD cy; COUNT i; r.corner.x = 2; r.corner.y = 20; r.extent.width = FIELD_WIDTH + 1; // XXX: Shouldn't the height be 1 less? This draws the bottom border // 1 pixel too low. Or if not, why do we need another box anyway? r.extent.height = 129 - r.corner.y; DrawStarConBox (&r, 1, SHADOWBOX_MEDIUM_COLOR, SHADOWBOX_DARK_COLOR, TRUE, DEVICES_BACK_COLOR); // print the "DEVICES" title SetContextFont (StarConFont); t.baseline.x = (STATUS_WIDTH >> 1) - 1; t.baseline.y = r.corner.y + 7; t.align = ALIGN_CENTER; t.pStr = GAME_STRING (DEVICE_STRING_BASE); t.CharCount = (COUNT)~0; SetContextForeGroundColor (DEVICES_SELECTED_NAME_COLOR); font_DrawText (&t); s.origin.x = DEVICE_COL_0; cy = DEVICE_ORG_Y; // draw device icons and print names for (i = 0; i < MAX_VIS_DEVICES; ++i, cy += DEVICE_SPACING_Y) { COUNT devIndex = devState->topIndex + i; if (devIndex >= devState->count) break; // draw device icon s.origin.y = cy + ICON_OFS_Y; s.frame = SetAbsFrameIndex (MiscDataFrame, 77 + devState->list[devIndex]); DrawStamp (&s); DrawDevice (devState->list[devIndex], i, false); } }
// Pre: caller holds the graphics lock. static void DrawPickMeleeFrame (COUNT which_player) { CONTEXT oldContext; STAMP s; oldContext = SetContext (SpaceContext); s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player); s.origin.x = PICK_X_OFFS - RES_SCALE(3); // JMS_GFX s.origin.y = PICK_Y_OFFS - RES_SCALE(9) + ((1 - which_player) * PICK_SIDE_OFFS); DrawStamp (&s); // Draw the selection box to screen. SetContext (oldContext); }
static void buzzsaw_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (ElementPtr0->state_flags & DISAPPEARING) { ElementPtr0->state_flags &= ~DISAPPEARING; ElementPtr0->state_flags |= NONSOLID | CHANGING; ElementPtr0->life_span = 5; ElementPtr0->next.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 2); ElementPtr0->preprocess_func = splinter_preprocess; } }
static int hangar_anim_func (void *data) { DWORD TimeIn; STAMP s; Task task = (Task) data; COLORMAP ColorMap; RECT ClipRect; if (!pMenuState->CurString) { FinishTask (task); return -1; } s.origin.x = s.origin.y = 0; s.frame = SetAbsFrameIndex (pMenuState->CurFrame, 24); ClipRect = pMenuState->flash_rect1; ColorMap = SetAbsColorMapIndex (pMenuState->CurString, 0); TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { CONTEXT OldContext; RECT OldClipRect; LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); GetContextClipRect (&OldClipRect); SetContextClipRect (&ClipRect); ColorMap = SetRelColorMapIndex (ColorMap, 1); SetColorMap (GetColorMapAddress (ColorMap)); DrawStamp (&s); SetContextClipRect (&OldClipRect); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + ONE_SECOND / HANGAR_ANIM_RATE); TimeIn = GetTimeCounter (); } FinishTask (task); return 0; }
static void pump_up_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { RECT r; BYTE old_thrust_wait; HELEMENT hBlastElement; GetFrameRect (ElementPtr0->next.image.frame, &r); old_thrust_wait = ElementPtr0->thrust_wait; ElementPtr0->blast_offset = r.extent.width >> 1; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); // This new section kills suspended blaster pulses after sustaining massive burst damage. if (ElementPtr1->mass_points >= ElementPtr0->mass_points) { ElementPtr0->postprocess_func = 0; ElementPtr0->thrust_wait = 0; ElementPtr0->state_flags |= DISAPPEARING; } else ElementPtr0->thrust_wait = old_thrust_wait; if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = MIN_PUMPITUDE_ANIMS + (ElementPtr0->turn_wait & ~REVERSE_DIR); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], MAX_PUMP * NUM_PUMP_ANIMS); UnlockElement (hBlastElement); } }
// Cross out the icon for the dead ship. // 'frame' is the PickMeleeFrame for the player. // 'shipI' is the index in the ship list. // Pre: caller holds the graphics lock. static void CrossOutShip (FRAME frame, COUNT shipNr) { CONTEXT OldContext; STAMP s; BYTE row = PickMelee_GetShipRow (shipNr); BYTE col = PickMelee_GetShipColumn (shipNr); OldContext = SetContext (OffScreenContext); SetContextFGFrame (frame); s.origin.x = RES_SCALE(3) + ((ICON_WIDTH + RES_SCALE(2)) * col); // JMS_GFX s.origin.y = RES_SCALE(9) + ((ICON_HEIGHT + RES_SCALE(2)) * row); // JMS_GFX s.frame = SetAbsFrameIndex (StatusFrame, 3); // Cross for through the ship image. DrawStamp (&s); SetContext (OldContext); }
static void blaster_preprocess (ELEMENT *ElementPtr) { BYTE wait; switch (ElementPtr->mass_points) { case BLASTER_DAMAGE * 1: if (GetFrameIndex (ElementPtr->current.image.frame) < 8) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; } break; case BLASTER_DAMAGE * 3: if (GetFrameIndex (ElementPtr->current.image.frame) < 19) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 16); ElementPtr->state_flags |= CHANGING; break; } if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else if ((wait = HINIBBLE (ElementPtr->turn_wait))) { COUNT facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if (TrackShip (ElementPtr, &facing) > 0) SetVelocityVector (&ElementPtr->velocity, BLASTER_SPEED, facing); ElementPtr->turn_wait = MAKE_BYTE (wait, wait); } }
// Reads a piece of screen into a passed FRAME or a newly created one DRAWABLE LoadDisplayPixmap (const RECT *area, FRAME frame) { // TODO: This should just return a FRAME instead of DRAWABLE DRAWABLE buffer = GetFrameParentDrawable (frame); COUNT index; if (!buffer) { // asked to create a new DRAWABLE instead buffer = CreateDrawable (WANT_PIXMAP | MAPPED_TO_DISPLAY, area->extent.width, area->extent.height, 1); if (!buffer) return NULL; index = 0; } else { index = GetFrameIndex (frame); } frame = SetAbsFrameIndex (CaptureDrawable (buffer), index); if (_CurFramePtr->Type != SCREEN_DRAWABLE || frame->Type == SCREEN_DRAWABLE || !(GetFrameParentDrawable (frame)->Flags & MAPPED_TO_DISPLAY)) { log_add (log_Warning, "Unimplemented function activated: " "LoadDisplayPixmap()"); } else { TFB_Image *img = frame->image; TFB_DrawScreen_CopyToImage (img, area, TFB_SCREEN_MAIN); } ReleaseDrawable (frame); return buffer; }
static void flame_napalm_preprocess (ELEMENT *ElementPtr) { ZeroVelocityComponents (&ElementPtr->velocity); if (ElementPtr->state_flags & NONSOLID) { ElementPtr->state_flags &= ~NONSOLID; ElementPtr->state_flags |= APPEARING; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); } /* turn_wait is abused here to store the speed of the decay animation */ else if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { if (ElementPtr->life_span <= NUM_NAPALM_FADES * (NAPALM_DECAY_RATE + 1) || GetFrameIndex ( ElementPtr->current.image.frame ) != NUM_NAPALM_FADES) ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->current.image.frame); else if (ElementPtr->life_span > NUM_NAPALM_FADES * (NAPALM_DECAY_RATE + 1)) ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, GetFrameCount (ElementPtr->current.image.frame) - 1 ); /* turn_wait is abused here to store the speed of the decay * animation. */ ElementPtr->turn_wait = NAPALM_DECAY_RATE; ElementPtr->state_flags |= CHANGING; } }
static void asteroid_preprocess (ELEMENT *ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (ElementPtr->thrust_wait & (1 << 7)) --frame_index; else ++frame_index; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, NORMALIZE_FACING (frame_index)); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = (unsigned char)(ElementPtr->thrust_wait & ((1 << 7) - 1)); } }
// When gas expires, display animation of the gas dissolving. static void gas_death (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->hShip) { HELEMENT hDissolve; ELEMENT *ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); if ((hDissolve = AllocElement ())) { ELEMENT *DissolvePtr; LockElement (hDissolve, &DissolvePtr); DissolvePtr->playerNr = ElementPtr->playerNr; DissolvePtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING; DissolvePtr->turn_wait = 0; DissolvePtr->life_span = NUM_DISSOLVE_FRAMES; DissolvePtr->current.location.x = ElementPtr->current.location.x; DissolvePtr->current.location.y = ElementPtr->current.location.y; DissolvePtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; DissolvePtr->current.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, LAST_SHOCKWAVE_INDEX); DissolvePtr->preprocess_func = gas_death_animation; SetElementStarShip (DissolvePtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[DissolvePtr->PrimIndex], STAMP_PRIM); UnlockElement (hDissolve); PutElement (hDissolve); } UnlockElement (StarShipPtr->hShip); } }
// The spray preprocess function animates spray. static void spray_preprocess (ELEMENT *ElementPtr) { // Abusing thrust_wait to slow down the anim. if (ElementPtr->thrust_wait > 0) --ElementPtr->thrust_wait; // Move to next frame. else { // Abusing thrust_wait to slow down the anim. (Should help performance a bit.) ElementPtr->thrust_wait = 1; // This makes the gas animate even if the ships are not moving and the screen is stationary. ElementPtr->state_flags |= CHANGING; if (GetFrameIndex (ElementPtr->current.image.frame) < LAST_SPRAY_INDEX) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); // This is a safeguard to prevent going over frame boundaries if someone messes up the // MISSILE_LIFE <-> LAST_SPRAY_INDEX <-> thrust_wait correspondence. else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 0); } }
static void flame_napalm_preprocess (ELEMENT *ElementPtr) { ZeroVelocityComponents (&ElementPtr->velocity); if (ElementPtr->state_flags & NONSOLID) { ElementPtr->state_flags &= ~NONSOLID; ElementPtr->state_flags |= APPEARING; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); } else if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { #define NUM_NAPALM_FADES 6 if (ElementPtr->life_span <= NUM_NAPALM_FADES * (NAPALM_WAIT + 1) || GetFrameIndex ( ElementPtr->current.image.frame ) != NUM_NAPALM_FADES) ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->current.image.frame); else if (ElementPtr->life_span > NUM_NAPALM_FADES * (NAPALM_WAIT + 1)) ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, GetFrameCount (ElementPtr->current.image.frame) - 1 ); ElementPtr->turn_wait = NAPALM_WAIT; ElementPtr->state_flags |= CHANGING; } }
static void pump_up_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { RECT r; BYTE old_thrust_wait; HELEMENT hBlastElement; GetFrameRect (ElementPtr0->next.image.frame, &r); old_thrust_wait = ElementPtr0->thrust_wait; ElementPtr0->blast_offset = r.extent.width >> 1; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->thrust_wait = old_thrust_wait; if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = MIN_PUMPITUDE_ANIMS + (ElementPtr0->turn_wait & ~REVERSE_DIR); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], MAX_PUMP * NUM_PUMP_ANIMS); UnlockElement (hBlastElement); } }