#include "../doomdef.h" #include "../d_player.h" #include "../m_random.h" #include "../k_kart.h" #include "../k_objects.h" #include "../p_local.h" #include "../r_main.h" #include "../s_sound.h" // TODO: general function static fixed_t K_GetPlayerSpeedRatio(player_t *player) { return FixedDiv(player->speed, K_GetKartSpeed(player, false, false)); } #define debris_type(o) ((o)->extravalue1) #define debris_bouncesleft(o) ((o)->threshold) enum { DEBRIS_ALPHA, DEBRIS_BETA, NUM_DEBRIS_TYPES }; struct debris_config { mobj_t * origin; angle_t angle; fixed_t speed; fixed_t scale; UINT8 type; }; static fixed_t get_speed_ratio (mobj_t *thing) { return thing->player ? K_GetPlayerSpeedRatio(thing->player) : FRACUNIT; } static void spawn_debris ( const struct debris_config * config, INT32 angle) { const fixed_t height_table[NUM_DEBRIS_TYPES] = { 50*FRACUNIT, 35*FRACUNIT, }; mobj_t *debris = P_SpawnMobjFromMobj( config->origin, 0, 0, 0, MT_ITEM_DEBRIS); debris_type(debris) = config->type; debris_bouncesleft(debris) = 1; P_InstaThrust(debris, config->angle + angle, config->speed); P_SetObjectMomZ(debris, FixedMul(config->scale, height_table[config->type]), false); debris->destscale = FixedMul(config->scale, 3 * debris->scale); P_SetScale(debris, debris->destscale); // Pass down color to dust particles debris->color = config->origin->color; } static void spawn_cloud ( mobj_t * collectible, mobj_t * collector, fixed_t base_speed) { const fixed_t min_speed = 90 * collectible->scale; const fixed_t scale = FixedDiv( max(base_speed, min_speed), min_speed); const INT16 spacing = (collectible->radius / 2) / collectible->scale; INT32 i; // Most of this code is from p_inter.c, MT_ITEMCAPSULE // dust effects for (i = 0; i < 10; i++) { mobj_t *puff = P_SpawnMobjFromMobj( collectible, P_RandomRange(-spacing, spacing) * FRACUNIT, P_RandomRange(-spacing, spacing) * FRACUNIT, P_RandomRange(0, 4 * spacing) * FRACUNIT, MT_SPINDASHDUST ); puff->color = collector->color; puff->colorized = true; puff->destscale = FixedMul(puff->destscale, scale); P_SetScale(puff, puff->destscale); puff->momz = puff->scale * P_MobjFlip(puff); P_InitAngle(puff, R_PointToAngle2( collectible->x, collectible->y, puff->x, puff->y)); P_Thrust(puff, puff->angle, 3 * puff->scale); puff->momx += collector->momx; puff->momy += collector->momy; puff->momz += collector->momz; } } static void rotate3d (mobj_t *debris) { const UINT8 steps = 30; debris->rollangle = M_RandomKey(steps) * (ANGLE_MAX / steps); } void Obj_SpawnItemDebrisEffects ( mobj_t * collectible, mobj_t * collector) { const fixed_t min_speed = 80 * collectible->scale; fixed_t base_speed = FixedMul(75 * mapobjectscale, get_speed_ratio(collector)); struct debris_config config; // Delayed effect for puffs of smoke that stick to and // glide off of the player mobj_t *spawner = P_SpawnMobjFromMobj(collectible, 0, 0, 0, MT_ITEM_DEBRIS_CLOUD_SPAWNER); P_SetTarget(&spawner->target, collector); config.origin = collectible; config.angle = K_MomentumAngle(collector); config.speed = max(base_speed, min_speed); config.scale = FixedDiv(config.speed, min_speed); config.type = DEBRIS_ALPHA; spawn_debris(&config, ANGLE_11hh); spawn_debris(&config, -(ANGLE_11hh)); config.type = DEBRIS_BETA; spawn_debris(&config, 3*ANGLE_22h/2); spawn_debris(&config, 3*ANGLE_22h/4); spawn_debris(&config, 0); spawn_debris(&config, -(3*ANGLE_22h/4)); spawn_debris(&config, -(3*ANGLE_22h/2)); spawn_cloud(collectible, collector, base_speed); S_StartSound(spawner, sfx_kc2e); S_StartSound(spawner, sfx_s1c9); } void Obj_ItemDebrisThink (mobj_t *debris) { const UINT8 frame = (debris->frame & FF_FRAMEMASK); if (debris->momz == 0) { P_KillMobj(debris, NULL, NULL, DMG_NORMAL); return; } rotate3d(debris); if (frame % 3 == 1) { mobj_t *ghost = P_SpawnGhostMobj(debris); ghost->fuse = 3; } if (debris_type(debris) == DEBRIS_ALPHA) { mobj_t *dust = P_SpawnMobjFromMobj( debris, 0, 0, 0, MT_SPINDASHDUST); P_SetScale(dust, (dust->destscale /= 3)); dust->color = debris->color; dust->colorized = true; dust->momx = debris->momx / 4; dust->momy = debris->momy / 4; dust->momz = debris->momz / 4; } } fixed_t Obj_ItemDebrisBounce ( mobj_t * debris, fixed_t momz) { if (debris_bouncesleft(debris) <= 0) { P_KillMobj(debris, NULL, NULL, DMG_NORMAL); return 0; } momz = -(momz); if (debris_type(debris) == DEBRIS_BETA) { momz /= 2; } debris_bouncesleft(debris)--; S_StartSound(debris, sfx_cdfm47); return momz; }