DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropWeaponPieces) { ACTION_PARAM_START(3); ACTION_PARAM_CLASS(p1, 0); ACTION_PARAM_CLASS(p2, 1); ACTION_PARAM_CLASS(p3, 2); for (int i = 0, j = 0, fineang = 0; i < 3; ++i) { const PClass *cls = j==0? p1 : j==1? p2 : p3; if (cls) { AActor *piece = Spawn (cls, self->x, self->y, self->z, ALLOW_REPLACE); if (piece != NULL) { piece->velx = self->velx + finecosine[fineang]; piece->vely = self->vely + finesine[fineang]; piece->velz = self->velz; piece->flags |= MF_DROPPED; fineang += FINEANGLES/3; j = (j == 0) ? (pr_quietusdrop() & 1) + 1 : 3-j; } } } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) { AActor *missile; angle_t an; if (!self->target) return; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); A_FaceTarget (self); // Change direction to ... self->angle += FATSPREAD; missile = P_SpawnMissile (self, self->target, spawntype); // [BC] If we're the server, tell clients to spawn the missile. if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( missile )) SERVERCOMMANDS_SpawnMissile( missile ); missile = P_SpawnMissile (self, self->target, spawntype); if (missile != NULL) { missile->angle += FATSPREAD; an = missile->angle >> ANGLETOFINESHIFT; missile->velx = FixedMul (missile->Speed, finecosine[an]); missile->vely = FixedMul (missile->Speed, finesine[an]); // [BC] If we're the server, tell clients to spawn the missile. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SpawnMissile( missile ); }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod) { ACTION_PARAM_START(1); ACTION_PARAM_CLASS(podtype, 0); AActor *mo; fixed_t x; fixed_t y; fixed_t z; if (self->special1 == MAX_GEN_PODS) { // Too many generated pods return; } x = self->x; y = self->y; z = self->z; mo = Spawn(podtype, x, y, ONFLOORZ, ALLOW_REPLACE); if (!P_CheckPosition (mo, x, y)) { // Didn't fit mo->Destroy (); return; } mo->SetState (mo->FindState("Grow")); P_ThrustMobj (mo, pr_makepod()<<24, (fixed_t)(4.5*FRACUNIT)); S_Sound (mo, CHAN_BODY, self->AttackSound, 1, ATTN_IDLE); self->special1++; // Increment generated pod count mo->master = self; // Link the generator to the pod return; }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1) { AActor *missile; angle_t an; if (!self->target) return; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); A_FaceTarget (self); // Change direction to ... self->angle += FATSPREAD; P_SpawnMissile (self, self->target, spawntype); missile = P_SpawnMissile (self, self->target, spawntype); if (missile != NULL) { missile->angle += FATSPREAD; an = missile->angle >> ANGLETOFINESHIFT; missile->velx = FixedMul (missile->Speed, finecosine[an]); missile->vely = FixedMul (missile->Speed, finesine[an]); }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BridgeInit) { angle_t startangle; AActor *ball; fixed_t cx, cy, cz; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(balltype, 0); if (balltype == NULL) balltype = PClass::FindClass("BridgeBall"); cx = self->x; cy = self->y; cz = self->z; startangle = pr_orbit() << 24; self->special1 = 0; // Spawn triad into world -- may be more than a triad now. int ballcount = self->args[2]==0 ? 3 : self->args[2]; for (int i = 0; i < ballcount; i++) { ball = Spawn(balltype, cx, cy, cz, ALLOW_REPLACE); ball->angle = startangle + (ANGLE_45/32) * (256/ballcount) * i; ball->target = self; CALL_ACTION(A_BridgeOrbit, ball); // [Dusk] bridge balls should not be included in full updates // as the bridge thing will spawn them instead. if (NETWORK_GetState() == NETSTATE_SERVER) ball->ulNetworkFlags |= NETFL_ALLOWCLIENTSPAWN; } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireArrow) { angle_t savedangle; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(ti, 0); if (self->player == NULL) return; AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } if (ti) { savedangle = self->angle; self->angle += pr_electric.Random2 () << (18 - self->player->mo->accuracy * 5 / 100); self->player->mo->PlayAttacking2 (); P_SpawnPlayerMissile (self, ti); self->angle = savedangle; S_Sound (self, CHAN_WEAPON, "weapons/xbowshoot", 1, ATTN_NORM); } }
static const PClass *GetSpawnType(DECLARE_PARAMINFO) { ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); if (spawntype == NULL) spawntype = PClass::FindClass("LostSoul"); return spawntype; }
// // A_PainAttack // Spawn a lost soul and launch it at the target // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) { if (!self->target) return; ACTION_PARAM_START(4); ACTION_PARAM_CLASS(spawntype, 0); ACTION_PARAM_ANGLE(angle, 1); ACTION_PARAM_INT(flags, 2); ACTION_PARAM_INT(limit, 3); if (spawntype == NULL) spawntype = PClass::FindClass("LostSoul"); if (!(flags & PAF_AIMFACING)) A_FaceTarget (self); A_PainShootSkull (self, self->angle+angle, spawntype, flags, limit); }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) { FSoundID sound; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); if (spawntype != NULL) { sound = GetDefaultByType(spawntype)->SeeSound; } else { spawntype = PClass::FindClass ("SpawnFire"); sound = "brain/spawn"; } SpawnFly(self, spawntype, sound); }
// // A_VileTarget // Spawn the hellfire // DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileTarget) { ACTION_PARAM_START(1); ACTION_PARAM_CLASS(fire,0); AActor *fog; if (!self->target) return; A_FaceTarget (self); fog = Spawn (fire, self->target->x, self->target->y, self->target->z, ALLOW_REPLACE); self->tracer = fog; fog->target = self; fog->tracer = self->target; A_Fire(fog, 0); }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain) { ACTION_PARAM_START(1); ACTION_PARAM_CLASS(gootype, 0); int count; int chance; AActor *goo; chance = pr_podpain (); if (chance < 128) { return; } for (count = chance > 240 ? 2 : 1; count; count--) { goo = Spawn(gootype, self->x, self->y, self->z + 48*FRACUNIT, ALLOW_REPLACE); goo->target = self; goo->velx = pr_podpain.Random2() << 9; goo->vely = pr_podpain.Random2() << 9; goo->velz = FRACUNIT/2 + (pr_podpain() << 9); } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) { DSpotState *state = DSpotState::GetSpotState(); AActor *targ; AActor *spit; bool isdefault = false; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); // shoot a cube at current target targ = state->GetNextInList(PClass::FindClass("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain)); if (targ != NULL) { if (spawntype == NULL) { spawntype = PClass::FindClass("SpawnShot"); isdefault = true; } // spawn brain missile spit = P_SpawnMissile (self, targ, spawntype); if (spit != NULL) { // Boss cubes should move freely to their destination so it's // probably best to disable all collision detection for them. if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION; spit->target = targ; spit->master = self; // [RH] Do this correctly for any trajectory. Doom would divide by 0 // if the target had the same y coordinate as the spitter. if ((spit->velx | spit->vely) == 0) { spit->special2 = 0; } else if (abs(spit->vely) > abs(spit->velx)) { spit->special2 = (targ->y - self->y) / spit->vely; } else { spit->special2 = (targ->x - self->x) / spit->velx; } // [GZ] Calculates when the projectile will have reached destination spit->special2 += level.maptime; spit->flags6 |= MF6_BOSSCUBE; } if (!isdefault) { S_Sound(self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NONE); } else { // compatibility fallback S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE); } } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) { angle_t angle; angle_t slope; player_t *player; AActor *linetarget; int actualdamage; ACTION_PARAM_START(11); ACTION_PARAM_SOUND(fullsound, 0); ACTION_PARAM_SOUND(hitsound, 1); ACTION_PARAM_INT(damage, 2); ACTION_PARAM_CLASS(pufftype, 3); ACTION_PARAM_INT(Flags, 4); ACTION_PARAM_FIXED(Range, 5); ACTION_PARAM_ANGLE(Spread_XY, 6); ACTION_PARAM_ANGLE(Spread_Z, 7); ACTION_PARAM_FIXED(LifeSteal, 8); ACTION_PARAM_INT(lifestealmax, 9); ACTION_PARAM_CLASS(armorbonustype, 10); if (NULL == (player = self->player)) { return; } if (pufftype == NULL) pufftype = PClass::FindClass(NAME_BulletPuff); if (damage == 0) damage = 2; if (!(Flags & SF_NORANDOM)) damage *= (pr_saw()%10+1); // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) if (Range == 0) Range = MELEERANGE+1; angle = self->angle + (pr_saw.Random2() * (Spread_XY / 255)); slope = P_AimLineAttack (self, angle, Range, &linetarget) + (pr_saw.Random2() * (Spread_Z / 255)); AWeapon *weapon = self->player->ReadyWeapon; if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO)) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { if ((Flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64)) { player->extralight = !player->extralight; } S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return; } if (Flags & SF_RANDOMLIGHTHIT) { int randVal = pr_saw(); if (randVal < 64) { player->extralight = 0; } else if (randVal < 160) { player->extralight = 1; } else { player->extralight = 2; } } if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) { if (Flags & SF_STEALARMOR) { if (!armorbonustype) armorbonustype = PClass::FindClass("ArmorBonus"); if (armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus))) { ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn (armorbonustype, 0,0,0, NO_REPLACE)); armorbonus->SaveAmount *= (actualdamage * LifeSteal) >> FRACBITS; armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax; armorbonus->flags |= MF_DROPPED; armorbonus->ClearCounters(); if (!armorbonus->CallTryPickup (self)) { armorbonus->Destroy (); } } } else {