//----------------------------------------------------------------------------- // // Copyright 2016-2018 Christoph Oelckers // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses/ // //----------------------------------------------------------------------------- // // VM thunks for internal functions of actor classes // // Important note about this file: Since everything in here is supposed to be called // from JIT-compiled VM code it needs to be very careful about calling conventions. // As a result none of the integer sized struct types may be used as function // arguments, because current C++ calling conventions require them to be passed // by reference. The JIT code, however will pass them by value so any direct native function // taking such an argument needs to receive it as a naked int. // //----------------------------------------------------------------------------- #include "vm.h" #include "r_defs.h" #include "g_levellocals.h" #include "s_sound.h" #include "p_local.h" #include "v_font.h" #include "gstrings.h" #include "a_keys.h" #include "sbar.h" #include "doomstat.h" #include "p_acs.h" #include "a_pickups.h" #include "a_specialspot.h" #include "actorptrselect.h" #include "a_weapons.h" #include "d_player.h" #include "p_setup.h" #include "i_music.h" #include "p_terrain.h" #include "p_checkposition.h" #include "p_linetracedata.h" #include "p_local.h" #include "p_effect.h" #include "p_spec.h" #include "actorinlines.h" #include "p_enemy.h" #include "gi.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); void PrintPickupMessage(bool localview, const FString &str); bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nullptr, FSoundID sound = 0); // FCheckPosition requires explicit construction and destruction when used in the VM static void FCheckPosition_C(void *mem) { new(mem) FCheckPosition; } DEFINE_ACTION_FUNCTION_NATIVE(_FCheckPosition, _Constructor, FCheckPosition_C) { PARAM_SELF_STRUCT_PROLOGUE(FCheckPosition); FCheckPosition_C(self); return 0; } static void FCheckPosition_D(FCheckPosition *self) { self->~FCheckPosition(); } DEFINE_ACTION_FUNCTION_NATIVE(_FCheckPosition, _Destructor, FCheckPosition_D) { PARAM_SELF_STRUCT_PROLOGUE(FCheckPosition); self->~FCheckPosition(); return 0; } static void ClearLastRipped(FCheckPosition *self) { self->LastRipped.Clear(); } DEFINE_ACTION_FUNCTION_NATIVE(_FCheckPosition, ClearLastRipped, ClearLastRipped) { PARAM_SELF_STRUCT_PROLOGUE(FCheckPosition); self->LastRipped.Clear(); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(DObject, SetMusicVolume, I_SetMusicVolume) { PARAM_PROLOGUE; PARAM_FLOAT(vol); I_SetMusicVolume(vol); return 0; } //===================================================================================== // // AActor exports (this will be expanded) // //===================================================================================== DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetPointer, COPY_AAPTR) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(ptr); ACTION_RETURN_OBJECT(COPY_AAPTR(self, ptr)); } //========================================================================== // // Custom sound functions. // //========================================================================== static void NativeStopSound(AActor *actor, int slot) { S_StopSound(actor, slot); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StopSound, NativeStopSound) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(slot); S_StopSound(self, slot); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StopSounds, S_StopActorSounds) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(chanmin); PARAM_INT(chanmax); S_StopActorSounds(self, chanmin, chanmax); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundPitch, S_ChangeActorSoundPitch) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(channel); PARAM_FLOAT(pitch); S_ChangeActorSoundPitch(self, channel, pitch); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundVolume, S_ChangeActorSoundVolume) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(channel); PARAM_FLOAT(volume); S_ChangeActorSoundVolume(self, channel, volume); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND(soundid); PARAM_INT(channel); PARAM_FLOAT(volume); PARAM_BOOL(looping); PARAM_FLOAT(attenuation); PARAM_BOOL(local); PARAM_FLOAT(pitch); A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound) { PARAM_SELF_PROLOGUE(AActor); PARAM_SOUND(soundid); PARAM_INT(channel); PARAM_INT(flags); PARAM_FLOAT(volume); PARAM_FLOAT(attenuation); PARAM_FLOAT(pitch); PARAM_FLOAT(startTime); A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); return 0; } void A_StartSoundIfNotSame(AActor *self, int soundid, int checksoundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime) { if (!S_AreSoundsEquivalent (self, soundid, checksoundid)) A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSoundIfNotSame, A_StartSoundIfNotSame) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(soundid); PARAM_INT(checksoundid); PARAM_INT(channel); PARAM_INT(flags); PARAM_FLOAT(volume); PARAM_FLOAT(attenuation); PARAM_FLOAT(pitch); PARAM_FLOAT(startTime); A_StartSoundIfNotSame(self, soundid, checksoundid, channel, flags, volume, attenuation, pitch, startTime); return 0; } // direct native scripting export. static int S_IsActorPlayingSomethingID(AActor* actor, int channel, int sound_id) { return S_IsActorPlayingSomething(actor, channel, FSoundID::fromInt(sound_id)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, IsActorPlayingSound, S_IsActorPlayingSomethingID) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(channel); PARAM_SOUND(soundid); ACTION_RETURN_BOOL(S_IsActorPlayingSomething(self, channel, soundid)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckKeys, P_CheckKeys) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(locknum); PARAM_BOOL(remote); PARAM_BOOL(quiet); ACTION_RETURN_BOOL(P_CheckKeys(self, locknum, remote, quiet)); } static double deltaangleDbl(double a1, double a2) { return deltaangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, deltaangle, deltaangleDbl) // should this be global? { PARAM_PROLOGUE; PARAM_FLOAT(a1); PARAM_FLOAT(a2); ACTION_RETURN_FLOAT(deltaangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees()); } static double absangleDbl(double a1, double a2) { return absangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, absangle, absangleDbl) // should this be global? { PARAM_PROLOGUE; PARAM_FLOAT(a1); PARAM_FLOAT(a2); ACTION_RETURN_FLOAT(absangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees()); } static double Distance2DSquared(AActor *self, AActor *other) { return self->Distance2DSquared(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Distance2DSquared, Distance2DSquared) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance2DSquared(other)); } static double Distance3DSquared(AActor *self, AActor *other) { return self->Distance3DSquared(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Distance3DSquared, Distance3DSquared) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance3DSquared(other)); } static double Distance2D(AActor *self, AActor *other) { return self->Distance2D(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Distance2D, Distance2D) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance2D(other)); } static double Distance3D(AActor *self, AActor *other) { return self->Distance3D(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Distance3D, Distance3D) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_FLOAT(self->Distance3D(other)); } static void AddZ(AActor *self, double addz, bool moving) { self->AddZ(addz, moving); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AddZ, AddZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(addz); PARAM_BOOL(moving); self->AddZ(addz, moving); return 0; } static void SetZ(AActor *self, double z) { self->SetZ(z); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetZ, SetZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(z); self->SetZ(z); return 0; } static void SetDamage(AActor *self, int dmg) { self->SetDamage(dmg); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetDamage, SetDamage) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(dmg); self->SetDamage(dmg); return 0; } static double PitchFromVel(AActor* self) { return self->Vel.Pitch().Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, PitchFromVel, PitchFromVel) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_FLOAT(PitchFromVel(self)); } // This combines all 3 variations of the internal function static void VelFromAngle(AActor *self, double speed, double angle) { if (speed == 1e37) { self->VelFromAngle(); } else { if (angle == 1e37) { self->VelFromAngle(speed); } else { self->VelFromAngle(speed, DAngle::fromDeg(angle)); } } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, VelFromAngle, VelFromAngle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(speed); PARAM_FLOAT(angle); VelFromAngle(self, speed, angle); return 0; } static void Vel3DFromAngle(AActor *self, double speed, double angle, double pitch) { self->Vel3DFromAngle(DAngle::fromDeg(angle), DAngle::fromDeg(pitch), speed); } // This combines all 3 variations of the internal function DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vel3DFromAngle, Vel3DFromAngle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(speed); PARAM_ANGLE(angle); PARAM_ANGLE(pitch); self->Vel3DFromAngle(angle, pitch, speed); return 0; } // This combines all 3 variations of the internal function static void Thrust(AActor *self, double speed, double angle) { if (speed == 1e37) { self->Thrust(); } else { if (angle == 1e37) { self->Thrust(speed); } else { self->Thrust(DAngle::fromDeg(angle), speed); } } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Thrust, Thrust) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(speed); PARAM_FLOAT(angle); Thrust(self, speed, angle); return 0; } static double AngleTo(AActor *self, AActor *targ, bool absolute) { return self->AngleTo(PARAM_NULLCHECK(targ, targ), absolute).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AngleTo, AngleTo) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(targ, AActor); PARAM_BOOL(absolute); ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees()); } static void AngleToVector(double angle, double length, DVector2 *result) { *result = DAngle::fromDeg(angle).ToVector(length); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AngleToVector, AngleToVector) { PARAM_PROLOGUE; PARAM_ANGLE(angle); PARAM_FLOAT(length); ACTION_RETURN_VEC2(angle.ToVector(length)); } static void RotateVector(double x, double y, double angle, DVector2 *result) { *result = DVector2(x, y).Rotated(angle); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RotateVector, RotateVector) { PARAM_PROLOGUE; PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_ANGLE(angle); ACTION_RETURN_VEC2(DVector2(x, y).Rotated(angle)); } static double Normalize180(double angle) { return DAngle::fromDeg(angle).Normalized180().Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Normalize180, Normalize180) { PARAM_PROLOGUE; PARAM_ANGLE(angle); ACTION_RETURN_FLOAT(angle.Normalized180().Degrees()); } static double DistanceBySpeed(AActor *self, AActor *targ, double speed) { return self->DistanceBySpeed(PARAM_NULLCHECK(targ, targ), speed); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, DistanceBySpeed, DistanceBySpeed) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(targ, AActor); PARAM_FLOAT(speed); ACTION_RETURN_FLOAT(self->DistanceBySpeed(targ, speed)); } static void SetXYZ(AActor *self, double x, double y, double z) { self->SetXYZ(x, y, z); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetXYZ, SetXYZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); self->SetXYZ(x, y, z); return 0; } static void Vec2Angle(AActor *self, double length, double angle, bool absolute, DVector2 *result) { *result = self->Vec2Angle(length, DAngle::fromDeg(angle), absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2Angle, Vec2Angle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(length); PARAM_ANGLE(angle); PARAM_BOOL(absolute); ACTION_RETURN_VEC2(self->Vec2Angle(length, angle, absolute)); } static void Vec3To(AActor *self, AActor *t, DVector3 *result) { *result = self->Vec3To(PARAM_NULLCHECK(t, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec3To, Vec3To) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(t, AActor) ACTION_RETURN_VEC3(self->Vec3To(t)); } static void Vec2To(AActor *self, AActor *t, DVector2 *result) { *result = self->Vec2To(PARAM_NULLCHECK(t, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2To, Vec2To) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(t, AActor) ACTION_RETURN_VEC2(self->Vec2To(t)); } static void Vec3Angle(AActor *self, double length, double angle, double z, bool absolute, DVector3 *result) { *result = self->Vec3Angle(length, DAngle::fromDeg(angle), z, absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec3Angle, Vec3Angle) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(length) PARAM_ANGLE(angle); PARAM_FLOAT(z); PARAM_BOOL(absolute); ACTION_RETURN_VEC3(self->Vec3Angle(length, angle, z, absolute)); } static void Vec2OffsetZ(AActor *self, double x, double y, double z, bool absolute, DVector3 *result) { *result = self->Vec2OffsetZ(x, y, z, absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2OffsetZ, Vec2OffsetZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); PARAM_BOOL(absolute); ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } static void Vec2Offset(AActor *self, double x, double y, bool absolute, DVector2 *result) { *result = self->Vec2Offset(x, y, absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2Offset, Vec2Offset) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_BOOL(absolute); ACTION_RETURN_VEC2(self->Vec2Offset(x, y, absolute)); } static void Vec3Offset(AActor *self, double x, double y, double z, bool absolute, DVector3 *result) { *result = self->Vec3Offset(x, y, z, absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec3Offset, Vec3Offset) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); PARAM_BOOL(absolute); ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute)); } static void ZS_PosRelative(AActor *self, sector_t *sec, DVector3 *result) { *result = self->PosRelative(sec); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, PosRelative, ZS_PosRelative) { PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(sec, sector_t); ACTION_RETURN_VEC3(self->PosRelative(sec)); } static void RestoreDamage(AActor *self) { self->DamageVal = self->GetDefault()->DamageVal; self->DamageFunc = self->GetDefault()->DamageFunc; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RestoreDamage, RestoreDamage) { PARAM_SELF_PROLOGUE(AActor); RestoreDamage(self); return 0; } static int PlayerNumber(AActor *self) { return self->player ? self->Level->PlayerNum(self->player) : 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, PlayerNumber, PlayerNumber) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_INT(PlayerNumber(self)); } static void SetFriendPlayer(AActor *self, player_t *player) { self->SetFriendPlayer(player); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetFriendPlayer, SetFriendPlayer) { PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(player, player_t); self->SetFriendPlayer(player); return 0; } void ClearBounce(AActor *self) { self->BounceFlags = 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearBounce, ClearBounce) { PARAM_SELF_PROLOGUE(AActor); ClearBounce(self); return 0; } static int CountsAsKill(AActor *self) { return self->CountsAsKill(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CountsAsKill, CountsAsKill) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(self->CountsAsKill()); } static int IsZeroDamage(AActor *self) { return self->IsZeroDamage(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, IsZeroDamage, IsZeroDamage) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(self->IsZeroDamage()); } static void ClearInterpolation(AActor *self) { self->ClearInterpolation(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearInterpolation, ClearInterpolation) { PARAM_SELF_PROLOGUE(AActor); self->ClearInterpolation(); return 0; } static int ApplyDamageFactors(PClassActor *itemcls, int damagetype, int damage, int defdamage) { DmgFactors &df = itemcls->ActorInfo()->DamageFactors; if (df.Size() != 0) { return (df.Apply(ENamedName(damagetype), damage)); } else { return (defdamage); } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ApplyDamageFactors, ApplyDamageFactors) { PARAM_PROLOGUE; PARAM_CLASS(itemcls, AActor); PARAM_NAME(damagetype); PARAM_INT(damage); PARAM_INT(defdamage); ACTION_RETURN_INT(ApplyDamageFactors(itemcls, damagetype.GetIndex(), damage, defdamage)); } static void RestoreSpecialPosition(AActor *self) { self->RestoreSpecialPosition(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_RestoreSpecialPosition, RestoreSpecialPosition) { PARAM_SELF_PROLOGUE(AActor); self->RestoreSpecialPosition(); return 0; } static double GetBobOffset(AActor *self, double frac) { return self->GetBobOffset(frac); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetBobOffset, GetBobOffset) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(frac); ACTION_RETURN_FLOAT(self->GetBobOffset(frac)); } static void SetIdle(AActor *self, bool nofunction) { self->SetIdle(nofunction); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetIdle, SetIdle) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(nofunction); self->SetIdle(nofunction); return 0; } static int SpawnHealth(AActor *self) { return self->SpawnHealth(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SpawnHealth, SpawnHealth) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_INT(self->SpawnHealth()); } // Why does this exist twice? DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetSpawnHealth, SpawnHealth) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_INT(self->SpawnHealth()); } void Revive(AActor *self) { self->Revive(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Revive, Revive) { PARAM_SELF_PROLOGUE(AActor); self->Revive(); return 0; } static double GetCameraHeight(AActor *self) { return self->GetCameraHeight(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetCameraHeight, GetCameraHeight) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_FLOAT(self->GetCameraHeight()); } static FDropItem *GetDropItems(AActor *self) { return self->GetDropItems(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetDropItems, GetDropItems) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_POINTER(self->GetDropItems()); } static double GetGravity(AActor *self) { return self->GetGravity(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetGravity, GetGravity) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_FLOAT(self->GetGravity()); } static void GetTag(AActor *self, const FString &def, FString *result) { *result = self->GetTag(def.Len() == 0 ? nullptr : def.GetChars()); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetTag, GetTag) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(def); FString res; GetTag(self, def, &res); ACTION_RETURN_STRING(res); } static void GetCharacterName(AActor *self, FString *result) { *result = self->GetCharacterName(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetCharacterName, GetCharacterName) { PARAM_SELF_PROLOGUE(AActor); FString res; GetCharacterName(self, &res); ACTION_RETURN_STRING(res); } static void SetTag(AActor *self, const FString &def) { if (def.IsEmpty()) self->Tag = nullptr; else self->Tag = self->mStringPropertyData.Alloc(def); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetTag, SetTag) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(def); SetTag(self, def); return 0; } static void ClearCounters(AActor *self) { self->ClearCounters(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearCounters, ClearCounters) { PARAM_SELF_PROLOGUE(AActor); self->ClearCounters(); return 0; } static int GetModifiedDamage(AActor *self, int type, int damage, bool passive, AActor *inflictor, AActor *source, int flags) { return self->GetModifiedDamage(ENamedName(type), damage, passive, inflictor, source, flags); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetModifiedDamage, GetModifiedDamage) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME(type); PARAM_INT(damage); PARAM_BOOL(passive); PARAM_OBJECT(inflictor, AActor); PARAM_OBJECT(source, AActor); PARAM_INT(flags); ACTION_RETURN_INT(self->GetModifiedDamage(type, damage, passive, inflictor, source, flags)); } static int ApplyDamageFactor(AActor *self, int type, int damage) { return self->ApplyDamageFactor(ENamedName(type), damage); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ApplyDamageFactor, ApplyDamageFactor) { PARAM_SELF_PROLOGUE(AActor); PARAM_NAME(type); PARAM_INT(damage); ACTION_RETURN_INT(self->ApplyDamageFactor(type, damage)); } double GetDefaultSpeed(PClassActor *type); DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetDefaultSpeed, GetDefaultSpeed) { PARAM_PROLOGUE; PARAM_CLASS(type, AActor); ACTION_RETURN_FLOAT(GetDefaultSpeed(type)); } static int isTeammate(AActor *self, AActor *other) { return self->IsTeammate(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, isTeammate, isTeammate) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsTeammate(other)); } static int GetSpecies(AActor *self) { return self->GetSpecies().GetIndex(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetSpecies, GetSpecies) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_INT(GetSpecies(self)); } static int isFriend(AActor *self, AActor *other) { return self->IsFriend(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFriend, isFriend) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsFriend(other)); } static int isHostile(AActor *self, AActor *other) { return self->IsHostile(PARAM_NULLCHECK(other, other)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, isHostile, isHostile) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(other, AActor); ACTION_RETURN_BOOL(self->IsHostile(other)); } static FTerrainDef *GetFloorTerrain(AActor *self) { return &Terrains[P_GetThingFloorType(self)]; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetFloorTerrain, GetFloorTerrain) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_POINTER(GetFloorTerrain(self)); } static int P_FindUniqueTID(FLevelLocals *Level, int start, int limit) { return Level->FindUniqueTID(start, limit); } DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, FindUniqueTid, P_FindUniqueTID) { PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); PARAM_INT(start); PARAM_INT(limit); ACTION_RETURN_INT(P_FindUniqueTID(self, start, limit)); } static void RemoveFromHash(AActor *self) { self->SetTID(0); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RemoveFromHash, RemoveFromHash) { PARAM_SELF_PROLOGUE(AActor); RemoveFromHash(self); return 0; } static void ChangeTid(AActor *self, int tid) { self->SetTID(tid); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ChangeTid, ChangeTid) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(tid); ChangeTid(self, tid); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, FindFloorCeiling, P_FindFloorCeiling) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(flags); P_FindFloorCeiling(self, flags); return 0; } static int TeleportMove(AActor *self, double x, double y, double z, bool telefrag, bool modify) { return P_TeleportMove(self, DVector3(x, y, z), telefrag, modify); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TeleportMove, TeleportMove) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); PARAM_BOOL(telefrag); PARAM_BOOL(modify); ACTION_RETURN_BOOL(P_TeleportMove(self, DVector3(x, y, z), telefrag, modify)); } static double ZS_GetFriction(AActor *self, double *mf) { double friction; *mf = P_GetMoveFactor(self, &friction); return friction; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetFriction, ZS_GetFriction) { PARAM_SELF_PROLOGUE(AActor); double friction, movefactor = P_GetMoveFactor(self, &friction); if (numret > 1) ret[1].SetFloat(movefactor); if (numret > 0) ret[0].SetFloat(friction); return numret; } static int CheckPosition(AActor *self, double x, double y, bool actorsonly, FCheckPosition *tm) { if (tm) { return (P_CheckPosition(self, DVector2(x, y), *tm, actorsonly)); } else { return (P_CheckPosition(self, DVector2(x, y), actorsonly)); } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckPosition, CheckPosition) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_BOOL(actorsonly); PARAM_POINTER(tm, FCheckPosition); ACTION_RETURN_BOOL(CheckPosition(self, x, y, actorsonly, tm)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TestMobjLocation, P_TestMobjLocation) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(P_TestMobjLocation(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TestMobjZ, P_TestMobjZ) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(quick); AActor *on = nullptr; bool retv = P_TestMobjZ(self, quick, &on); if (numret > 1) ret[1].SetObject(on); if (numret > 0) ret[0].SetInt(retv); return numret; } static int TryMove(AActor *self ,double x, double y, int dropoff, bool missilecheck, FCheckPosition *tm) { if (tm == nullptr) { return (P_TryMove(self, DVector2(x, y), dropoff, nullptr, missilecheck)); } else { return (P_TryMove(self, DVector2(x, y), dropoff, nullptr, *tm, missilecheck)); } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TryMove, TryMove) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_INT(dropoff); PARAM_BOOL(missilecheck); PARAM_POINTER(tm, FCheckPosition); ACTION_RETURN_BOOL(TryMove(self, x, y, dropoff, missilecheck, tm)); } static int CheckMove(AActor *self ,double x, double y, int flags, FCheckPosition *tm) { if (tm == nullptr) { return (P_CheckMove(self, DVector2(x, y), flags)); } else { return (P_CheckMove(self, DVector2(x, y), *tm, flags)); } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckMove, CheckMove) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_INT(flags); PARAM_POINTER(tm, FCheckPosition); ACTION_RETURN_BOOL(CheckMove(self, x, y, flags, tm)); } static double AimLineAttack(AActor *self, double angle, double distance, FTranslatedLineTarget *pLineTarget, double vrange, int flags, AActor *target, AActor *friender) { flags &= ~ALF_IGNORENOAUTOAIM; // just to be safe. This flag is not supposed to be accesible to scripting. return P_AimLineAttack(self, DAngle::fromDeg(angle), distance, pLineTarget, DAngle::fromDeg(vrange), flags, target, friender).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AimLineAttack, AimLineAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_ANGLE(angle); PARAM_FLOAT(distance); PARAM_OUTPOINTER(pLineTarget, FTranslatedLineTarget); PARAM_ANGLE(vrange); PARAM_INT(flags); PARAM_OBJECT(target, AActor); PARAM_OBJECT(friender, AActor); ACTION_RETURN_FLOAT(P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees()); } static AActor *ZS_LineAttack(AActor *self, double angle, double distance, double pitch, int damage, int damageType, PClassActor *puffType, int flags, FTranslatedLineTarget *victim, double offsetz, double offsetforward, double offsetside, int *actualdamage) { if (puffType == nullptr) puffType = PClass::FindActor(NAME_BulletPuff); // P_LineAttack does not work without a puff to take info from. return P_LineAttack(self, DAngle::fromDeg(angle), distance, DAngle::fromDeg(pitch), damage, ENamedName(damageType), puffType, flags, victim, actualdamage, offsetz, offsetforward, offsetside); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineAttack, ZS_LineAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(angle); PARAM_FLOAT(distance); PARAM_FLOAT(pitch); PARAM_INT(damage); PARAM_INT(damageType); PARAM_CLASS(puffType, AActor); PARAM_INT(flags); PARAM_OUTPOINTER(victim, FTranslatedLineTarget); PARAM_FLOAT(offsetz); PARAM_FLOAT(offsetforward); PARAM_FLOAT(offsetside); int acdmg; auto puff = ZS_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, offsetz, offsetforward, offsetside, &acdmg); if (numret > 0) ret[0].SetObject(puff); if (numret > 1) ret[1].SetInt(acdmg), numret = 2; return numret; } static int LineTrace(AActor *self, double angle, double distance, double pitch, int flags, double offsetz, double offsetforward, double offsetside, FLineTraceData *data) { return P_LineTrace(self,DAngle::fromDeg(angle),distance,DAngle::fromDeg(pitch),flags,offsetz,offsetforward,offsetside,data); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineTrace, LineTrace) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(angle); PARAM_FLOAT(distance); PARAM_FLOAT(pitch); PARAM_INT(flags); PARAM_FLOAT(offsetz); PARAM_FLOAT(offsetforward); PARAM_FLOAT(offsetside); PARAM_OUTPOINTER(data, FLineTraceData); ACTION_RETURN_BOOL(P_LineTrace(self,DAngle::fromDeg(angle),distance,DAngle::fromDeg(pitch),flags,offsetz,offsetforward,offsetside,data)); } static void TraceBleedAngle(AActor *self, int damage, double angle, double pitch) { P_TraceBleed(damage, self, DAngle::fromDeg(angle), DAngle::fromDeg(pitch)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TraceBleedAngle, TraceBleedAngle) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(damage); PARAM_FLOAT(angle); PARAM_FLOAT(pitch); P_TraceBleed(damage, self, DAngle::fromDeg(angle), DAngle::fromDeg(pitch)); return 0; } static void TraceBleedTLT(FTranslatedLineTarget *self, int damage, AActor *missile) { P_TraceBleed(damage, self, PARAM_NULLCHECK(missile, missile)); } DEFINE_ACTION_FUNCTION_NATIVE(_FTranslatedLineTarget, TraceBleed, TraceBleedTLT) { PARAM_SELF_STRUCT_PROLOGUE(FTranslatedLineTarget); PARAM_INT(damage); PARAM_OBJECT_NOT_NULL(missile, AActor); P_TraceBleed(damage, self, missile); return 0; } static void TraceBleedA(AActor *self, int damage, AActor *missile) { if (missile) P_TraceBleed(damage, self, missile); else P_TraceBleed(damage, self); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TraceBleed, TraceBleedA) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(damage); PARAM_OBJECT(missile, AActor); TraceBleedA(self, damage, missile); return 0; } static void RailAttack(AActor *self, FRailParams *p) { p->source = self; P_RailAttack(p); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RailAttack, RailAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(p, FRailParams); RailAttack(self, p); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, UsePuzzleItem, P_UsePuzzleItem) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(puzznum); ACTION_RETURN_BOOL(P_UsePuzzleItem(self, puzznum)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetRadiusDamage, P_GetRadiusDamage) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(thing, AActor); PARAM_INT(damage); PARAM_INT(distance); PARAM_INT(fulldmgdistance); PARAM_BOOL(oldradiusdmg); ACTION_RETURN_INT(P_GetRadiusDamage(self, thing, damage, distance, fulldmgdistance, oldradiusdmg)); } static int RadiusAttack(AActor *self, AActor *bombsource, int bombdamage, int bombdistance, int damagetype, int flags, int fulldamagedistance, int species) { return P_RadiusAttack(self, bombsource, bombdamage, bombdistance, ENamedName(damagetype), flags, fulldamagedistance, ENamedName(species)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RadiusAttack, RadiusAttack) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(bombsource, AActor); PARAM_INT(bombdamage); PARAM_INT(bombdistance); PARAM_INT(damagetype); PARAM_INT(flags); PARAM_INT(fulldamagedistance); PARAM_INT(species); ACTION_RETURN_INT(RadiusAttack(self, bombsource, bombdamage, bombdistance, damagetype, flags, fulldamagedistance, species)); } static int ZS_GetSpriteIndex(int sprt) { return GetSpriteIndex(FName(ENamedName(sprt)).GetChars(), false); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetSpriteIndex, ZS_GetSpriteIndex) { PARAM_PROLOGUE; PARAM_INT(sprt); ACTION_RETURN_INT(ZS_GetSpriteIndex(sprt)); } static PClassActor *ZS_GetReplacement(PClassActor *c) { return c->GetReplacement(currentVMLevel); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetReplacement, ZS_GetReplacement) { PARAM_PROLOGUE; PARAM_POINTER(c, PClassActor); ACTION_RETURN_POINTER(ZS_GetReplacement(c)); } static PClassActor *ZS_GetReplacee(PClassActor *c) { return c->GetReplacee(currentVMLevel); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetReplacee, ZS_GetReplacee) { PARAM_PROLOGUE; PARAM_POINTER(c, PClassActor); ACTION_RETURN_POINTER(ZS_GetReplacee(c)); } static void DrawSplash(AActor *self, int count, double angle, int kind) { P_DrawSplash(self->Level, count, self->Pos(), DAngle::fromDeg(angle), kind); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, DrawSplash, DrawSplash) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(count); PARAM_FLOAT(angle); PARAM_INT(kind); P_DrawSplash(self->Level, count, self->Pos(), DAngle::fromDeg(angle), kind); return 0; } static void UnlinkFromWorld(AActor *self, FLinkContext *ctx) { self->UnlinkFromWorld(ctx); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, UnlinkFromWorld, UnlinkFromWorld) { PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(ctx, FLinkContext); self->UnlinkFromWorld(ctx); // fixme return 0; } static void LinkToWorld(AActor *self, FLinkContext *ctx) { self->LinkToWorld(ctx); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LinkToWorld, LinkToWorld) { PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(ctx, FLinkContext); self->LinkToWorld(ctx); return 0; } static void SetOrigin(AActor *self, double x, double y, double z, bool moving) { self->SetOrigin(x, y, z, moving); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetOrigin, SetOrigin) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); PARAM_BOOL(moving); self->SetOrigin(x, y, z, moving); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RoughMonsterSearch, P_RoughMonsterSearch) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(distance); PARAM_BOOL(onlyseekable); PARAM_BOOL(frontonly); PARAM_FLOAT(fov); ACTION_RETURN_OBJECT(P_RoughMonsterSearch(self, distance, onlyseekable, frontonly, fov)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckSight, P_CheckSight) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(target, AActor); PARAM_INT(flags); ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); } static void GiveSecret(AActor *self, bool printmessage, bool playsound) { P_GiveSecret(self->Level, self, printmessage, playsound, -1); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GiveSecret, GiveSecret) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(printmessage); PARAM_BOOL(playsound); GiveSecret(self, printmessage, playsound); return 0; } static int ZS_GetMissileDamage(AActor *self, int mask, int add, int pick_pointer) { self = COPY_AAPTR(self, pick_pointer); return self ? self->GetMissileDamage(mask, add) : 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetMissileDamage, ZS_GetMissileDamage) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(mask); PARAM_INT(add); PARAM_INT(pick_pointer); ACTION_RETURN_INT(ZS_GetMissileDamage(self, mask, add, pick_pointer)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SoundAlert, P_NoiseAlert) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(target, AActor); PARAM_BOOL(splash); PARAM_FLOAT(maxdist); P_NoiseAlert(self, target, splash, maxdist); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, HitFriend, P_HitFriend) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(P_HitFriend(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, MonsterMove, P_SmartMove) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(P_SmartMove(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, NewChaseDir, P_NewChaseDir) { PARAM_SELF_PROLOGUE(AActor); P_NewChaseDir(self); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RandomChaseDir, P_RandomChaseDir) { PARAM_SELF_PROLOGUE(AActor); P_RandomChaseDir(self); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, IsVisible, P_IsVisible) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(other, AActor); PARAM_BOOL(allaround); PARAM_POINTER(params, FLookExParams); ACTION_RETURN_BOOL(P_IsVisible(self, other, allaround, params)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForMonsters, P_LookForMonsters) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(P_LookForMonsters(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForTID, P_LookForTID) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(allaround); PARAM_POINTER(params, FLookExParams); ACTION_RETURN_BOOL(P_LookForTID(self, allaround, params)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForEnemies, P_LookForEnemies) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(allaround); PARAM_POINTER(params, FLookExParams); ACTION_RETURN_BOOL(P_LookForEnemies(self, allaround, params)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LookForPlayers, P_LookForPlayers) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(allaround); PARAM_POINTER(params, FLookExParams); ACTION_RETURN_BOOL(P_LookForPlayers(self, allaround, params)); } static int CheckMonsterUseSpecials(AActor *self) { spechit_t spec; int good = 0; if (!(self->flags6 & MF6_NOTRIGGER)) { while (spechit.Pop (spec)) { // [RH] let monsters push lines, as well as use them if (((self->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, self, 0, SPAC_Use)) || ((self->flags2 & MF2_PUSHWALL) && P_ActivateLine (spec.line, self, 0, SPAC_Push))) { good |= spec.line == self->BlockingLine ? 1 : 2; } } } else spechit.Clear(); return good; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckMonsterUseSpecials, CheckMonsterUseSpecials) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_INT(CheckMonsterUseSpecials(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Wander, A_Wander) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(flags); A_Wander(self, flags); return 0; } //========================================================================== // // A_Chase and variations // //========================================================================== static void A_FastChase(AActor *self) { A_DoChase(self, true, self->MeleeState, self->MissileState, true, true, false, 0); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_FastChase, A_FastChase) { PARAM_SELF_PROLOGUE(AActor); A_FastChase(self); return 0; } static void A_VileChase(AActor *self) { if (!P_CheckForResurrection(self, true)) { A_DoChase(self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false, 0); } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_VileChase, A_VileChase) { PARAM_SELF_PROLOGUE(AActor); A_VileChase(self); return 0; } static void A_ExtChase(AActor *self, bool domelee, bool domissile, bool playactive, bool nightmarefast) { // Now that A_Chase can handle state label parameters, this function has become rather useless... A_DoChase(self, false, domelee ? self->MeleeState : NULL, domissile ? self->MissileState : NULL, playactive, nightmarefast, false, 0); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_ExtChase, A_ExtChase) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(domelee); PARAM_BOOL(domissile); PARAM_BOOL(playactive); PARAM_BOOL(nightmarefast); A_ExtChase(self, domelee, domissile, playactive, nightmarefast); return 0; } int CheckForResurrection(AActor *self, FState* state, int sound) { return P_CheckForResurrection(self, false, state, sound); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_CheckForResurrection, CheckForResurrection) { PARAM_SELF_PROLOGUE(AActor); PARAM_STATE(state); PARAM_INT(sound); ACTION_RETURN_BOOL(P_CheckForResurrection(self, false, state, sound)); } static void ZS_Face(AActor *self, AActor *faceto, double max_turn, double max_pitch, double ang_offset, double pitch_offset, int flags, double z_add) { A_Face(self, faceto, DAngle::fromDeg(max_turn), DAngle::fromDeg(max_pitch), DAngle::fromDeg(ang_offset), DAngle::fromDeg(pitch_offset), flags, z_add); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Face, ZS_Face) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(faceto, AActor) PARAM_ANGLE(max_turn) PARAM_ANGLE(max_pitch) PARAM_ANGLE(ang_offset) PARAM_ANGLE(pitch_offset) PARAM_INT(flags) PARAM_FLOAT(z_add) A_Face(self, faceto, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckBossDeath, CheckBossDeath) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(CheckBossDeath(self)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_BossDeath, A_BossDeath) { PARAM_SELF_PROLOGUE(AActor); A_BossDeath(self); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Substitute, StaticPointerSubstitution) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(replace, AActor); StaticPointerSubstitution(self, replace); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(_PlayerPawn, Substitute, StaticPointerSubstitution) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(replace, AActor); StaticPointerSubstitution(self, replace); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(_MorphedMonster, Substitute, StaticPointerSubstitution) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(replace, AActor); StaticPointerSubstitution(self, replace); return 0; } DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetSpawnableType, P_GetSpawnableType) { PARAM_PROLOGUE; PARAM_INT(num); ACTION_RETURN_POINTER(P_GetSpawnableType(num)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_NoBlocking, A_Unblock) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(drop); A_Unblock(self, drop); return 0; } static void CopyBloodColor(AActor* self, AActor* other) { if (self && other) { self->BloodColor = other->BloodColor; self->BloodTranslation = other->BloodTranslation; } } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CopyBloodColor, CopyBloodColor) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(other, AActor); CopyBloodColor(self, other); return 0; } //===================================================================================== // // Inventory exports // //===================================================================================== DEFINE_ACTION_FUNCTION_NATIVE(AInventory, PrintPickupMessage, PrintPickupMessage) { PARAM_PROLOGUE; PARAM_BOOL(localview); PARAM_STRING(str); PrintPickupMessage(localview, str); return 0; } //===================================================================================== // // Key exports // //===================================================================================== DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyTypeCount, P_GetKeyTypeCount) { PARAM_PROLOGUE; ACTION_RETURN_INT(P_GetKeyTypeCount()); } DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyType, P_GetKeyType) { PARAM_PROLOGUE; PARAM_INT(num); ACTION_RETURN_POINTER(P_GetKeyType(num)); } //===================================================================================== // // 3D Floor exports // //===================================================================================== int CheckFor3DFloorHit(AActor *self, double z, bool trigger) { return P_CheckFor3DFloorHit(self, z, trigger); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DFloorHit, CheckFor3DFloorHit) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(z); PARAM_BOOL(trigger); ACTION_RETURN_BOOL(P_CheckFor3DFloorHit(self, z, trigger)); } int CheckFor3DCeilingHit(AActor *self, double z, bool trigger) { return P_CheckFor3DCeilingHit(self, z, trigger); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DCeilingHit, CheckFor3DCeilingHit) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(z); PARAM_BOOL(trigger); ACTION_RETURN_BOOL(P_CheckFor3DCeilingHit(self, z, trigger)); } static int isFrozen(AActor *self) { return self->isFrozen(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFrozen, isFrozen) { PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(isFrozen(self)); } //=========================================================================== // // PlayerPawn functions // //=========================================================================== DEFINE_ACTION_FUNCTION_NATIVE(APlayerPawn, MarkPlayerSounds, S_MarkPlayerSounds) { PARAM_SELF_PROLOGUE(AActor); S_MarkPlayerSounds(self); return 0; } static void GetPrintableDisplayNameJit(PClassActor *cls, FString *result) { *result = cls->GetDisplayName(); } DEFINE_ACTION_FUNCTION_NATIVE(APlayerPawn, GetPrintableDisplayName, GetPrintableDisplayNameJit) { PARAM_PROLOGUE; PARAM_CLASS(type, AActor); ACTION_RETURN_STRING(type->GetDisplayName()); } static void SetViewPos(AActor *self, double x, double y, double z, int flags) { if (!self->ViewPos) { self->ViewPos = Create(); } DVector3 pos = { x,y,z }; self->ViewPos->Set(pos, flags); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetViewPos, SetViewPos) { PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(x); PARAM_FLOAT(y); PARAM_FLOAT(z); PARAM_INT(flags); SetViewPos(self, x, y, z, flags); return 0; } IMPLEMENT_CLASS(DViewPosition, false, false); DEFINE_FIELD_X(ViewPosition, DViewPosition, Offset) DEFINE_FIELD_X(ViewPosition, DViewPosition, Flags) DEFINE_FIELD(DThinker, Level) DEFINE_FIELD(AActor, snext) DEFINE_FIELD(AActor, player) DEFINE_FIELD_NAMED(AActor, __Pos, pos) DEFINE_FIELD_NAMED(AActor, __Pos.X, x) DEFINE_FIELD_NAMED(AActor, __Pos.Y, y) DEFINE_FIELD_NAMED(AActor, __Pos.Z, z) DEFINE_FIELD(AActor, SpriteOffset) DEFINE_FIELD(AActor, WorldOffset) DEFINE_FIELD(AActor, Prev) DEFINE_FIELD(AActor, SpriteAngle) DEFINE_FIELD(AActor, SpriteRotation) DEFINE_FIELD(AActor, VisibleStartAngle) DEFINE_FIELD(AActor, VisibleStartPitch) DEFINE_FIELD(AActor, VisibleEndAngle) DEFINE_FIELD(AActor, VisibleEndPitch) DEFINE_FIELD_NAMED(AActor, Angles.Yaw, angle) DEFINE_FIELD_NAMED(AActor, Angles.Pitch, pitch) DEFINE_FIELD_NAMED(AActor, Angles.Roll, roll) DEFINE_FIELD(AActor, Vel) DEFINE_FIELD_NAMED(AActor, Vel.X, velx) DEFINE_FIELD_NAMED(AActor, Vel.Y, vely) DEFINE_FIELD_NAMED(AActor, Vel.Z, velz) DEFINE_FIELD_NAMED(AActor, Vel.X, momx) DEFINE_FIELD_NAMED(AActor, Vel.Y, momy) DEFINE_FIELD_NAMED(AActor, Vel.Z, momz) DEFINE_FIELD(AActor, Speed) DEFINE_FIELD(AActor, FloatSpeed) DEFINE_FIELD(AActor, sprite) DEFINE_FIELD(AActor, frame) DEFINE_FIELD(AActor, Scale) DEFINE_FIELD_NAMED(AActor, Scale.X, scalex) DEFINE_FIELD_NAMED(AActor, Scale.Y, scaley) DEFINE_FIELD(AActor, RenderStyle) DEFINE_FIELD(AActor, picnum) DEFINE_FIELD(AActor, Alpha) DEFINE_FIELD(AActor, fillcolor) DEFINE_FIELD_NAMED(AActor, Sector, CurSector) // clashes with type 'sector'. DEFINE_FIELD(AActor, subsector) DEFINE_FIELD(AActor, ceilingz) DEFINE_FIELD(AActor, floorz) DEFINE_FIELD(AActor, dropoffz) DEFINE_FIELD(AActor, floorsector) DEFINE_FIELD(AActor, floorpic) DEFINE_FIELD(AActor, floorterrain) DEFINE_FIELD(AActor, ceilingsector) DEFINE_FIELD(AActor, ceilingpic) DEFINE_FIELD(AActor, Height) DEFINE_FIELD(AActor, radius) DEFINE_FIELD(AActor, renderradius) DEFINE_FIELD(AActor, projectilepassheight) DEFINE_FIELD(AActor, tics) DEFINE_FIELD_NAMED(AActor, state, curstate) // clashes with type 'state'. DEFINE_FIELD_NAMED(AActor, DamageVal, Damage) // name differs for historic reasons DEFINE_FIELD(AActor, projectileKickback) DEFINE_FIELD(AActor, VisibleToTeam) DEFINE_FIELD(AActor, special1) DEFINE_FIELD(AActor, special2) DEFINE_FIELD(AActor, specialf1) DEFINE_FIELD(AActor, specialf2) DEFINE_FIELD(AActor, weaponspecial) DEFINE_FIELD(AActor, health) DEFINE_FIELD(AActor, movedir) DEFINE_FIELD(AActor, visdir) DEFINE_FIELD(AActor, movecount) DEFINE_FIELD(AActor, strafecount) DEFINE_FIELD(AActor, target) DEFINE_FIELD(AActor, master) DEFINE_FIELD(AActor, tracer) DEFINE_FIELD(AActor, LastHeard) DEFINE_FIELD(AActor, lastenemy) DEFINE_FIELD(AActor, LastLookActor) DEFINE_FIELD(AActor, reactiontime) DEFINE_FIELD(AActor, threshold) DEFINE_FIELD(AActor, DefThreshold) DEFINE_FIELD(AActor, SpawnPoint) DEFINE_FIELD(AActor, SpawnAngle) DEFINE_FIELD(AActor, StartHealth) DEFINE_FIELD(AActor, WeaveIndexXY) DEFINE_FIELD(AActor, WeaveIndexZ) DEFINE_FIELD(AActor, skillrespawncount) DEFINE_FIELD(AActor, args) DEFINE_FIELD(AActor, Mass) DEFINE_FIELD(AActor, special) DEFINE_FIELD(AActor, tid) DEFINE_FIELD(AActor, TIDtoHate) DEFINE_FIELD(AActor, waterlevel) DEFINE_FIELD(AActor, waterdepth) DEFINE_FIELD(AActor, Score) DEFINE_FIELD(AActor, accuracy) DEFINE_FIELD(AActor, stamina) DEFINE_FIELD(AActor, meleerange) DEFINE_FIELD(AActor, PainThreshold) DEFINE_FIELD(AActor, Gravity) DEFINE_FIELD(AActor, Floorclip) DEFINE_FIELD(AActor, DamageType) DEFINE_FIELD(AActor, DamageTypeReceived) DEFINE_FIELD(AActor, FloatBobPhase) DEFINE_FIELD(AActor, FloatBobStrength) DEFINE_FIELD(AActor, RipperLevel) DEFINE_FIELD(AActor, RipLevelMin) DEFINE_FIELD(AActor, RipLevelMax) DEFINE_FIELD(AActor, Species) DEFINE_FIELD(AActor, alternative) DEFINE_FIELD(AActor, goal) DEFINE_FIELD(AActor, MinMissileChance) DEFINE_FIELD(AActor, LastLookPlayerNumber) DEFINE_FIELD(AActor, SpawnFlags) DEFINE_FIELD(AActor, meleethreshold) DEFINE_FIELD(AActor, maxtargetrange) DEFINE_FIELD(AActor, bouncefactor) DEFINE_FIELD(AActor, wallbouncefactor) DEFINE_FIELD(AActor, bouncecount) DEFINE_FIELD(AActor, Friction) DEFINE_FIELD(AActor, FastChaseStrafeCount) DEFINE_FIELD(AActor, pushfactor) DEFINE_FIELD(AActor, lastpush) DEFINE_FIELD(AActor, activationtype) DEFINE_FIELD(AActor, lastbump) DEFINE_FIELD(AActor, DesignatedTeam) DEFINE_FIELD(AActor, BlockingMobj) DEFINE_FIELD(AActor, BlockingLine) DEFINE_FIELD(AActor, Blocking3DFloor) DEFINE_FIELD(AActor, BlockingCeiling) DEFINE_FIELD(AActor, BlockingFloor) DEFINE_FIELD(AActor, freezetics) DEFINE_FIELD(AActor, PoisonDamage) DEFINE_FIELD(AActor, PoisonDamageType) DEFINE_FIELD(AActor, PoisonDuration) DEFINE_FIELD(AActor, PoisonPeriod) DEFINE_FIELD(AActor, PoisonDamageReceived) DEFINE_FIELD(AActor, PoisonDamageTypeReceived) DEFINE_FIELD(AActor, PoisonDurationReceived) DEFINE_FIELD(AActor, PoisonPeriodReceived) DEFINE_FIELD(AActor, Poisoner) DEFINE_FIELD_NAMED(AActor, Inventory, Inv) // clashes with type 'Inventory'. DEFINE_FIELD(AActor, smokecounter) DEFINE_FIELD(AActor, FriendPlayer) DEFINE_FIELD(AActor, Translation) DEFINE_FIELD(AActor, AttackSound) DEFINE_FIELD(AActor, DeathSound) DEFINE_FIELD(AActor, SeeSound) DEFINE_FIELD(AActor, PainSound) DEFINE_FIELD(AActor, ActiveSound) DEFINE_FIELD(AActor, UseSound) DEFINE_FIELD(AActor, BounceSound) DEFINE_FIELD(AActor, WallBounceSound) DEFINE_FIELD(AActor, CrushPainSound) DEFINE_FIELD(AActor, MaxDropOffHeight) DEFINE_FIELD(AActor, MaxStepHeight) DEFINE_FIELD(AActor, MaxSlopeSteepness) DEFINE_FIELD(AActor, PainChance) DEFINE_FIELD(AActor, PainType) DEFINE_FIELD(AActor, DeathType) DEFINE_FIELD(AActor, DamageFactor) DEFINE_FIELD(AActor, DamageMultiply) DEFINE_FIELD(AActor, TeleFogSourceType) DEFINE_FIELD(AActor, TeleFogDestType) DEFINE_FIELD(AActor, SpawnState) DEFINE_FIELD(AActor, SeeState) DEFINE_FIELD(AActor, MeleeState) DEFINE_FIELD(AActor, MissileState) DEFINE_FIELD(AActor, ConversationRoot) DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) DEFINE_FIELD(AActor, fountaincolor) DEFINE_FIELD(AActor, CameraHeight) DEFINE_FIELD(AActor, CameraFOV) DEFINE_FIELD(AActor, RadiusDamageFactor) DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(AActor, WoundHealth) DEFINE_FIELD(AActor, BloodColor) DEFINE_FIELD(AActor, BloodTranslation) DEFINE_FIELD(AActor, RenderHidden) DEFINE_FIELD(AActor, RenderRequired) DEFINE_FIELD(AActor, friendlyseeblocks) DEFINE_FIELD(AActor, SpawnTime) DEFINE_FIELD(AActor, InventoryID) DEFINE_FIELD(AActor, ThruBits) DEFINE_FIELD(AActor, ViewPos) DEFINE_FIELD_NAMED(AActor, ViewAngles.Yaw, viewangle) DEFINE_FIELD_NAMED(AActor, ViewAngles.Pitch, viewpitch) DEFINE_FIELD_NAMED(AActor, ViewAngles.Roll, viewroll) DEFINE_FIELD(AActor, LightLevel) DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos); DEFINE_FIELD_NAMED_X(FCheckPosition, FCheckPosition, sector, cursector); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, floorz); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, ceilingz); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, dropoffz); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, floorpic); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, floorterrain); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, floorsector); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, ceilingpic); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, ceilingsector); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, touchmidtex); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, abovemidtex); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, floatok); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, FromPMove); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, ceilingline); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, stepthing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, DoRipping); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, portalstep); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, portalgroup); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, PushTime); DEFINE_FIELD_X(FRailParams, FRailParams, source); DEFINE_FIELD_X(FRailParams, FRailParams, damage); DEFINE_FIELD_X(FRailParams, FRailParams, offset_xy); DEFINE_FIELD_X(FRailParams, FRailParams, offset_z); DEFINE_FIELD_X(FRailParams, FRailParams, color1); DEFINE_FIELD_X(FRailParams, FRailParams, color2); DEFINE_FIELD_X(FRailParams, FRailParams, maxdiff); DEFINE_FIELD_X(FRailParams, FRailParams, flags); DEFINE_FIELD_X(FRailParams, FRailParams, puff); DEFINE_FIELD_X(FRailParams, FRailParams, angleoffset); DEFINE_FIELD_X(FRailParams, FRailParams, pitchoffset); DEFINE_FIELD_X(FRailParams, FRailParams, distance); DEFINE_FIELD_X(FRailParams, FRailParams, duration); DEFINE_FIELD_X(FRailParams, FRailParams, sparsity); DEFINE_FIELD_X(FRailParams, FRailParams, drift); DEFINE_FIELD_X(FRailParams, FRailParams, spawnclass); DEFINE_FIELD_X(FRailParams, FRailParams, SpiralOffset); DEFINE_FIELD_X(FRailParams, FRailParams, limit); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitActor); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitLine); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitSector); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Hit3DFloor); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitTexture); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitLocation); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitDir); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Distance); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, NumPortals); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LineSide); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LinePart); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, SectorPlane); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitType);