diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp index 8fce33324..f24ff146e 100644 --- a/src/g_doom/a_archvile.cpp +++ b/src/g_doom/a_archvile.cpp @@ -151,5 +151,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack) P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0); } - target->velz = Scale(thrust, 1000, target->Mass); + if (!(target->flags7 & MF7_DONTTHRUST)) + target->velz = Scale(thrust, 1000, target->Mass); } diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 7a11a2865..791021ae8 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1280,8 +1280,8 @@ public: // We can't use DTA_HUDRules since it forces a width and height. // Translation: No high res. - bool xright = rx < 0; - bool ybot = ry < 0; + bool xright = *x < 0 && !x.RelCenter(); + bool ybot = *y < 0 && !y.RelCenter(); w = (forceWidth < 0 ? texture->GetScaledWidthDouble() : forceWidth); h = (forceHeight < 0 ? texture->GetScaledHeightDouble() : forceHeight); diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp index d720b7b9b..d984bbdd3 100644 --- a/src/g_strife/a_loremaster.cpp +++ b/src/g_strife/a_loremaster.cpp @@ -14,27 +14,27 @@ class ALoreShot : public AActor { DECLARE_CLASS (ALoreShot, AActor) public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); + int DoSpecialDamage (AActor *victim, int damage, FName damagetype); }; IMPLEMENT_CLASS (ALoreShot) -int ALoreShot::DoSpecialDamage (AActor *target, int damage, FName damagetype) +int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype) { FVector3 thrust; - if (this->target != NULL && !(this->target->flags7 & MF7_DONTTHRUST)) + if (victim != NULL && target != NULL && !(victim->flags7 & MF7_DONTTHRUST)) { - thrust.X = float(this->target->x - target->x); - thrust.Y = float(this->target->y - target->y); - thrust.Z = float(this->target->z - target->z); + thrust.X = float(target->x - victim->x); + thrust.Y = float(target->y - victim->y); + thrust.Z = float(target->z - victim->z); thrust.MakeUnit(); - thrust *= float((255*50*FRACUNIT) / (target->Mass ? target->Mass : 1)); + thrust *= float((255*50*FRACUNIT) / (victim->Mass ? victim->Mass : 1)); - target->velx += fixed_t(thrust.X); - target->vely += fixed_t(thrust.Y); - target->velz += fixed_t(thrust.Z); + victim->velx += fixed_t(thrust.X); + victim->vely += fixed_t(thrust.Y); + victim->velz += fixed_t(thrust.Z); } return damage; } diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index eff53fc49..9a7715265 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -196,9 +196,9 @@ bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller) --mDesc->mSelectedItem; if (mDesc->mScrollPos > 0 && - mDesc->mSelectedItem == mDesc->mScrollTop + mDesc->mScrollPos) + mDesc->mSelectedItem <= mDesc->mScrollTop + mDesc->mScrollPos) { - mDesc->mScrollPos--; + mDesc->mScrollPos = MAX(mDesc->mSelectedItem - mDesc->mScrollTop - 1, 0); } if (mDesc->mSelectedItem < 0) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 36a68281e..7bf19a03b 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1278,7 +1278,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL) { int newdam = damage; - player->mo->Inventory->AbsorbDamage(damage, mod, newdam); + if (damage > 0) + { + player->mo->Inventory->AbsorbDamage(damage, mod, newdam); + } if (damage < TELEFRAG_DAMAGE) { // if we are telefragging don't let the damage value go below that magic value. Some further checks would fail otherwise. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index fea80f868..ef23ca0ba 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1970,6 +1970,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) { //int dir; //angle_t delta; + angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y); bool dontReflect = (mo->AdjustReflectionAngle(BlockingMobj, angle)); // Change angle for deflection/reflection @@ -1989,18 +1990,13 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) //dest->x - source->x FVector3 velocity(origin->x - mo->x, origin->y - mo->y, (origin->z + (origin->height/2)) - mo->z); velocity.Resize(speed); - angle = mo->angle >> ANGLETOFINESHIFT; mo->velx = (fixed_t)(velocity.X); mo->vely = (fixed_t)(velocity.Y); mo->velz = (fixed_t)(velocity.Z); - /* - mo->velx = FixedMul(mo->Speed, finecosine[angle]); - mo->vely = FixedMul(mo->Speed, finesine[angle]); - mo->velz = -mo->velz; - */ } else { + mo->angle = angle; angle >>= ANGLETOFINESHIFT; mo->velx = FixedMul(mo->Speed >> 1, finecosine[angle]); diff --git a/src/posix/sdl/sdlvideo.cpp b/src/posix/sdl/sdlvideo.cpp index 7a04ce901..309002456 100644 --- a/src/posix/sdl/sdlvideo.cpp +++ b/src/posix/sdl/sdlvideo.cpp @@ -286,7 +286,6 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer (int width, int height, bool fullscree } SDLFB *fb = new SDLFB (width, height, fullscreen); - retry = 0; // If we could not create the framebuffer, try again with slightly // different parameters in this order: @@ -327,6 +326,7 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer (int width, int height, bool fullscree ++retry; fb = static_cast(CreateFrameBuffer (width, height, fullscreen, NULL)); } + retry = 0; fb->SetFlash (flashColor, flashAmount); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 300ee7556..9db52f728 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1670,14 +1670,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) // //=========================================================================== -static void DoGiveInventory(AActor * receiver, DECLARE_PARAMINFO) +static void DoGiveInventory(AActor * receiver, bool use_aaptr, DECLARE_PARAMINFO) { - ACTION_PARAM_START(3); + ACTION_PARAM_START(2+use_aaptr); ACTION_PARAM_CLASS(mi, 0); ACTION_PARAM_INT(amount, 1); - ACTION_PARAM_INT(setreceiver, 2); - COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); + if (use_aaptr) + { + ACTION_PARAM_INT(setreceiver, 2); + COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); + } bool res=true; @@ -1685,6 +1688,11 @@ static void DoGiveInventory(AActor * receiver, DECLARE_PARAMINFO) if (mi) { AInventory *item = static_cast(Spawn (mi, 0, 0, 0, NO_REPLACE)); + if (!item) + { + ACTION_SET_RESULT(false); + return; + } if (item->IsKindOf(RUNTIME_CLASS(AHealth))) { item->Amount *= amount; @@ -1709,12 +1717,12 @@ static void DoGiveInventory(AActor * receiver, DECLARE_PARAMINFO) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveInventory) { - DoGiveInventory(self, PUSH_PARAMINFO); + DoGiveInventory(self, true, PUSH_PARAMINFO); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget) { - DoGiveInventory(self->target, PUSH_PARAMINFO); + DoGiveInventory(self->target, true, PUSH_PARAMINFO); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) @@ -1724,7 +1732,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) while ((mo = it.Next())) { - if (mo->master == self) DoGiveInventory(mo, PUSH_PARAMINFO); + if (mo->master == self) DoGiveInventory(mo, false, PUSH_PARAMINFO); } } @@ -1737,7 +1745,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) { while ((mo = it.Next())) { - if (mo->master == self->master && mo != self) DoGiveInventory(mo, PUSH_PARAMINFO); + if (mo->master == self->master && mo != self) DoGiveInventory(mo, false, PUSH_PARAMINFO); } } } @@ -1753,16 +1761,23 @@ enum TIF_NOTAKEINFINITE = 1, }; -void DoTakeInventory(AActor * receiver, DECLARE_PARAMINFO) +void DoTakeInventory(AActor * receiver, bool use_aaptr, DECLARE_PARAMINFO) { - ACTION_PARAM_START(4); + ACTION_PARAM_START(3+use_aaptr); ACTION_PARAM_CLASS(item, 0); ACTION_PARAM_INT(amount, 1); ACTION_PARAM_INT(flags, 2); - ACTION_PARAM_INT(setreceiver, 3); - if (!item) return; - COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); + if (!item) + { + ACTION_SET_RESULT(false); + return; + } + if (use_aaptr) + { + ACTION_PARAM_INT(setreceiver, 3); + COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); + } bool res = false; @@ -1794,12 +1809,12 @@ void DoTakeInventory(AActor * receiver, DECLARE_PARAMINFO) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeInventory) { - DoTakeInventory(self, PUSH_PARAMINFO); + DoTakeInventory(self, true, PUSH_PARAMINFO); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget) { - DoTakeInventory(self->target, PUSH_PARAMINFO); + DoTakeInventory(self->target, true, PUSH_PARAMINFO); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) @@ -1809,7 +1824,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) while ((mo = it.Next())) { - if (mo->master == self) DoTakeInventory(mo, PUSH_PARAMINFO); + if (mo->master == self) DoTakeInventory(mo, false, PUSH_PARAMINFO); } } @@ -1822,7 +1837,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings) { while ((mo = it.Next())) { - if (mo->master == self->master && mo != self) DoTakeInventory(mo, PUSH_PARAMINFO); + if (mo->master == self->master && mo != self) DoTakeInventory(mo, false, PUSH_PARAMINFO); } } } @@ -2504,12 +2519,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FadeTo) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetScale) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(3); ACTION_PARAM_FIXED(scalex, 0); ACTION_PARAM_FIXED(scaley, 1); + ACTION_PARAM_INT(ptr, 2); - self->scaleX = scalex; - self->scaleY = scaley ? scaley : scalex; + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + ref->scaleX = scalex; + ref->scaleY = scaley ? scaley : scalex; } //=========================================================================== @@ -3934,10 +3958,19 @@ enum DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(3); ACTION_PARAM_ANGLE(angle, 0); - ACTION_PARAM_INT(flags, 1) - self->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); + ACTION_PARAM_INT(flags, 1); + ACTION_PARAM_INT(ptr, 2); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + ref->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== @@ -3950,18 +3983,27 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(3); ACTION_PARAM_ANGLE(pitch, 0); ACTION_PARAM_INT(flags, 1); + ACTION_PARAM_INT(ptr, 2); - if (self->player != NULL || (flags & SPF_FORCECLAMP)) + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + if (ref->player != NULL || (flags & SPF_FORCECLAMP)) { // clamp the pitch we set int min, max; - if (self->player != NULL) + if (ref->player != NULL) { - min = self->player->MinPitch; - max = self->player->MaxPitch; + min = ref->player->MinPitch; + max = ref->player->MaxPitch; } else { @@ -3970,7 +4012,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) } pitch = clamp(pitch, min, max); } - self->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); + ref->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== @@ -3983,10 +4025,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(3); ACTION_PARAM_ANGLE(roll, 0); ACTION_PARAM_INT(flags, 1); - self->SetRoll(roll, !!(flags & SPF_INTERPOLATE)); + ACTION_PARAM_INT(ptr, 2); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + ref->SetRoll(roll, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== @@ -3999,20 +4050,29 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_FIXED(scale, 0); + ACTION_PARAM_INT(ptr, 1); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } INTBOOL was_moving = self->velx | self->vely | self->velz; - self->velx = FixedMul(self->velx, scale); - self->vely = FixedMul(self->vely, scale); - self->velz = FixedMul(self->velz, scale); + ref->velx = FixedMul(ref->velx, scale); + ref->vely = FixedMul(ref->vely, scale); + ref->velz = FixedMul(ref->velz, scale); // If the actor was previously moving but now is not, and is a player, // update its player variables. (See A_Stop.) if (was_moving) { - CheckStopped(self); + CheckStopped(ref); } } @@ -4029,12 +4089,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) ACTION_PARAM_FIXED(y, 1); ACTION_PARAM_FIXED(z, 2); ACTION_PARAM_INT(flags, 3); + ACTION_PARAM_INT(ptr, 4); - INTBOOL was_moving = self->velx | self->vely | self->velz; + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + INTBOOL was_moving = ref->velx | ref->vely | ref->velz; fixed_t vx = x, vy = y, vz = z; - fixed_t sina = finesine[self->angle >> ANGLETOFINESHIFT]; - fixed_t cosa = finecosine[self->angle >> ANGLETOFINESHIFT]; + fixed_t sina = finesine[ref->angle >> ANGLETOFINESHIFT]; + fixed_t cosa = finecosine[ref->angle >> ANGLETOFINESHIFT]; if (flags & 1) // relative axes - make x, y relative to actor's current angle { @@ -4043,15 +4112,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity) } if (flags & 2) // discard old velocity - replace old velocity with new velocity { - self->velx = vx; - self->vely = vy; - self->velz = vz; + ref->velx = vx; + ref->vely = vy; + ref->velz = vz; } else // add new velocity to old velocity { - self->velx += vx; - self->vely += vy; - self->velz += vz; + ref->velx += vx; + ref->vely += vy; + ref->velz += vz; } if (was_moving) @@ -5064,10 +5133,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_FIXED(speed, 0); + ACTION_PARAM_INT(ptr, 1); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } - self->Speed = speed; + ref->Speed = speed; } static bool DoCheckSpecies(AActor *mo, FName species, bool exclude) @@ -5656,7 +5734,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SwapTeleFog) // // A_SetFloatBobPhase // -// Changes the FloatBobPhase of the +// Changes the FloatBobPhase of the actor. //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatBobPhase) @@ -5669,6 +5747,73 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatBobPhase) self->FloatBobPhase = bob; } +//=========================================================================== +// A_SetHealth +// +// Changes the health of the actor. +// Takes a pointer as well. +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetHealth) +{ + ACTION_PARAM_START(2); + ACTION_PARAM_INT(health, 0); + ACTION_PARAM_INT(ptr, 1); + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (!mobj) + { + return; + } + + player_t *player = mobj->player; + if (player) + { + if (health <= 0) + player->mo->health = mobj->health = player->health = 1; //Copied from the buddha cheat. + else + player->mo->health = mobj->health = player->health = health; + } + else if (mobj) + { + if (health <= 0) + mobj->health = 1; + else + mobj->health = health; + } +} + +//=========================================================================== +// A_ResetHealth +// +// Resets the health of the actor to default, except if their dead. +// Takes a pointer. +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) +{ + ACTION_PARAM_START(1); + ACTION_PARAM_INT(ptr, 0); + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (!mobj) + { + return; + } + + player_t *player = mobj->player; + if (player && (player->mo->health > 0)) + { + player->health = player->mo->health = player->mo->GetDefault()->health; //Copied from the resurrect cheat. + } + else if (mobj && (mobj->health > 0)) + { + mobj->health = mobj->SpawnHealth(); + } +} + //=========================================================================== // // A_SetRipperLevel(int level) diff --git a/src/zstring.h b/src/zstring.h index 0104020fa..82c38142c 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -296,6 +296,16 @@ protected: static FNullStringData NullString; friend struct FStringData; + +private: + // Prevent these from being called as current practices are to use Compare. + // Without this FStrings will be accidentally compared against char* ptrs. + bool operator == (const FString &illegal) const; + bool operator != (const FString &illegal) const; + bool operator < (const FString &illegal) const; + bool operator > (const FString &illegal) const; + bool operator <= (const FString &illegal) const; + bool operator >= (const FString &illegal) const; }; namespace StringFormat diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index b2fa80c30..f0e68d9a5 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -231,7 +231,7 @@ ACTOR Actor native //: Thinker action native A_FadeIn(float reduce = 0.1, int flags = 0); action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true action native A_FadeTo(float target, float amount = 0.1, int flags = 0); - action native A_SetScale(float scalex, float scaley = 0); + action native A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT); action native A_SetMass(int mass); action native A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); action native A_CheckSight(state label); @@ -289,11 +289,11 @@ ACTOR Actor native //: Thinker action native A_DropWeaponPieces(class p1, class p2, class p3); action native A_PigPain (); action native A_MonsterRefire(int chance, state label); - action native A_SetAngle(float angle = 0, int flags = 0); - action native A_SetPitch(float pitch, int flags = 0); - action native A_SetRoll(float roll, int flags = 0); - action native A_ScaleVelocity(float scale); - action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); + action native A_SetAngle(float angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + action native A_SetPitch(float pitch, int flags = 0, int ptr = AAPTR_DEFAULT); + action native A_SetRoll(float roll, int flags = 0, int ptr = AAPTR_DEFAULT); + action native A_ScaleVelocity(float scale, int ptr = AAPTR_DEFAULT); + action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0, int ptr = AAPTR_DEFAULT); action native A_SetArg(int pos, int value); action native A_SetUserVar(name varname, int value); action native A_SetUserArray(name varname, int index, int value); @@ -302,7 +302,7 @@ ACTOR Actor native //: Thinker action native A_SetTics(int tics); action native A_SetDamageType(name damagetype); action native A_DropItem(class item, int dropamount = -1, int chance = 256); - action native A_SetSpeed(float speed); + action native A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT); action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); @@ -327,6 +327,8 @@ ACTOR Actor native //: Thinker action native A_SetTeleFog(name oldpos, name newpos); action native A_SwapTeleFog(); action native A_SetFloatBobPhase(int bob); + action native A_SetHealth(int health, int ptr = AAPTR_DEFAULT); + action native A_ResetHealth(int ptr = AAPTR_DEFAULT); action native A_SetRipperLevel(int level); action native A_SetRipMin(int min); action native A_SetRipMax(int max);