This commit is contained in:
Christoph Oelckers 2016-02-10 20:49:32 +01:00
commit 1098093ead
27 changed files with 164 additions and 169 deletions

View file

@ -230,20 +230,10 @@ include_directories( ${OPENGL_INCLUDE_DIR} )
if( NOT NO_OPENAL ) if( NOT NO_OPENAL )
find_package( OpenAL ) find_package( OpenAL )
mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR) mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR)
if( NOT WIN32 ) if( OPENAL_INCLUDE_DIR )
mark_as_advanced(CLEAR OPENAL_LIBRARY)
endif()
if( OPENAL_FOUND )
include_directories( ${OPENAL_INCLUDE_DIR} ) include_directories( ${OPENAL_INCLUDE_DIR} )
if( NOT WIN32 )
set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} )
endif()
else() else()
if ( NOT WIN32 ) set( NO_OPENAL ON )
set( NO_OPENAL ON )
else()
include_directories( ${OPENAL_INCLUDE_DIR} )
endif()
endif() endif()
endif() endif()

View file

@ -572,31 +572,11 @@ struct FStrifeDialogueNode;
struct fixedvec3 struct fixedvec3
{ {
fixed_t x, y, z; fixed_t x, y, z;
operator FVector3()
{
return FVector3(FIXED2FLOAT(x), FIXED2FLOAT(y), FIXED2FLOAT(z));
}
operator TVector3<double>()
{
return TVector3<double>(FIXED2DBL(x), FIXED2DBL(y), FIXED2DBL(z));
}
}; };
struct fixedvec2 struct fixedvec2
{ {
fixed_t x, y; fixed_t x, y;
operator FVector2()
{
return FVector2(FIXED2FLOAT(x), FIXED2FLOAT(y));
}
operator TVector2<double>()
{
return TVector2<double>(FIXED2DBL(x), FIXED2DBL(y));
}
}; };
class DDropItem : public DObject class DDropItem : public DObject

View file

@ -1715,7 +1715,7 @@ static void SetPointer(FState *state, PFunction *sym, int frame = 0)
{ {
if (sym == NULL) if (sym == NULL)
{ {
state->SetAction(NULL); state->ClearAction();
return; return;
} }
else else

View file

@ -98,7 +98,8 @@ enum
CLASSREG_PClassPlayerPawn, CLASSREG_PClassPlayerPawn,
CLASSREG_PClassType, CLASSREG_PClassType,
CLASSREG_PClassClass, CLASSREG_PClassClass,
CLASSREG_PClassWeaponPiece CLASSREG_PClassWeaponPiece,
CLASSREG_PClassPowerupGiver
}; };
struct ClassReg struct ClassReg

View file

@ -2165,6 +2165,7 @@ PClass *ClassReg::RegisterClass()
&PClassType::RegistrationInfo, &PClassType::RegistrationInfo,
&PClassClass::RegistrationInfo, &PClassClass::RegistrationInfo,
&PClassWeaponPiece::RegistrationInfo, &PClassWeaponPiece::RegistrationInfo,
&PClassPowerupGiver::RegistrationInfo,
}; };
// Skip classes that have already been registered // Skip classes that have already been registered
@ -2413,7 +2414,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
return static_cast<PClass *>(found); return static_cast<PClass *>(found);
} }
PClass *type = static_cast<PClass *>(GetClass()->CreateNew()); PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
Printf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
type->TypeName = name; type->TypeName = name;
type->ParentClass = this; type->ParentClass = this;

View file

@ -12,25 +12,6 @@
DECLARE_ACTION(A_SkullAttack) DECLARE_ACTION(A_SkullAttack)
static PClassActor *GetSpawnType(VMValue *param)
{
PClassActor *spawntype;
if (param == NULL || param->Type == REGT_NIL)
{
spawntype = NULL;
}
else
{
assert(param->Type == REGT_POINTER);
assert(param->atag == ATAG_OBJECT || param->a == NULL);
spawntype = (PClassActor *)param->a;
}
return (spawntype != NULL) ? spawntype : PClass::FindActor("LostSoul");
}
enum PA_Flags enum PA_Flags
{ {
PAF_NOSKULLATTACK = 1, PAF_NOSKULLATTACK = 1,
@ -47,7 +28,8 @@ void A_PainShootSkull (AActor *self, angle_t angle, PClassActor *spawntype, int
AActor *other; AActor *other;
int prestep; int prestep;
if (spawntype == NULL) return; if (spawntype == NULL) spawntype = PClass::FindActor("LostSoul");
assert(spawntype != NULL);
if (self->DamageType == NAME_Massacre) return; if (self->DamageType == NAME_Massacre) return;
// [RH] check to make sure it's not too close to the ceiling // [RH] check to make sure it's not too close to the ceiling
@ -182,8 +164,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_INT_OPT (limit) { limit = -1; } PARAM_INT_OPT (limit) { limit = -1; }
if (spawntype == NULL) spawntype = PClass::FindActor("LostSoul");
if (!(flags & PAF_AIMFACING)) if (!(flags & PAF_AIMFACING))
A_FaceTarget (self); A_FaceTarget (self);
A_PainShootSkull (self, self->angle+angle, spawntype, flags, limit); A_PainShootSkull (self, self->angle+angle, spawntype, flags, limit);
@ -193,11 +173,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
if (!self->target) if (!self->target)
return 0; return 0;
PClassActor *spawntype = GetSpawnType(numparam > NAP ? &param[NAP] : NULL);
A_FaceTarget (self); A_FaceTarget (self);
A_PainShootSkull (self, self->angle + ANG45, spawntype); A_PainShootSkull (self, self->angle + ANG45, spawntype);
A_PainShootSkull (self, self->angle - ANG45, spawntype); A_PainShootSkull (self, self->angle - ANG45, spawntype);
@ -207,12 +187,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainDie)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
PARAM_CLASS_OPT(spawntype, AActor) { spawntype = NULL; }
if (self->target != NULL && self->IsFriend(self->target)) if (self->target != NULL && self->IsFriend(self->target))
{ // And I thought you were my friend! { // And I thought you were my friend!
self->flags &= ~MF_FRIENDLY; self->flags &= ~MF_FRIENDLY;
} }
PClassActor *spawntype = GetSpawnType(numparam > NAP ? &param[NAP] : NULL);
A_Unblock(self, true); A_Unblock(self, true);
A_PainShootSkull (self, self->angle + ANG90, spawntype); A_PainShootSkull (self, self->angle + ANG90, spawntype);
A_PainShootSkull (self, self->angle + ANG180, spawntype); A_PainShootSkull (self, self->angle + ANG180, spawntype);

View file

@ -662,7 +662,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
} }
else else
{ // Seek { // Seek
self->angle = self->AngleTo(target); angle = self->AngleTo(target);
newAngle = true; newAngle = true;
} }
} }

View file

@ -65,59 +65,59 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
AWeapon *weapon = self->player->ReadyWeapon; AWeapon *weapon = self->player->ReadyWeapon;
pmo = player->mo; pmo = player->mo;
damage = 20+(pr_staffcheck()&15); damage = 20 + (pr_staffcheck() & 15);
max = pmo->GetMaxHealth(); max = pmo->GetMaxHealth();
puff = PClass::FindActor("CStaffPuff"); puff = PClass::FindActor("CStaffPuff");
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
angle = pmo->angle+i*(ANG45/16); angle = pmo->angle + i*(ANG45 / 16);
slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget); P_LineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
if (linetarget != NULL) if (linetarget != NULL)
{ {
pmo->angle = pmo->AngleTo(linetarget); pmo->angle = pmo->AngleTo(linetarget);
if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER) if (((linetarget->player && (!linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
&& (!(linetarget->flags2&(MF2_DORMANT|MF2_INVULNERABLE)))) && (!(linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE))))
{
newLife = player->health+(damage>>3);
newLife = newLife > max ? max : newLife;
if (newLife > player->health)
{ {
pmo->health = player->health = newLife; newLife = player->health + (damage >> 3);
} newLife = newLife > max ? max : newLife;
if (newLife > player->health)
{
pmo->health = player->health = newLife;
}
if (weapon != NULL) if (weapon != NULL)
{ {
FState * newstate = weapon->FindState("Drain"); FState * newstate = weapon->FindState("Drain");
if (newstate != NULL) P_SetPsprite(player, ps_weapon, newstate); if (newstate != NULL) P_SetPsprite(player, ps_weapon, newstate);
} }
}
if (weapon != NULL)
{
weapon->DepleteAmmo(weapon->bAltFire, false);
} }
if (weapon != NULL)
{
weapon->DepleteAmmo (weapon->bAltFire, false);
}
} }
break; break;
} }
angle = pmo->angle-i*(ANG45/16); angle = pmo->angle - i*(ANG45 / 16);
slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D); slope = P_AimLineAttack(player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget); P_LineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
if (linetarget != NULL) if (linetarget != NULL)
{ {
pmo->angle = pmo->AngleTo(linetarget); pmo->angle = pmo->AngleTo(linetarget);
if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER) if ((linetarget->player && (!linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
{ {
newLife = player->health+(damage>>4); newLife = player->health + (damage >> 4);
newLife = newLife > max ? max : newLife; newLife = newLife > max ? max : newLife;
pmo->health = player->health = newLife; pmo->health = player->health = newLife;
P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); P_SetPsprite(player, ps_weapon, weapon->FindState("Drain"));
} }
if (weapon != NULL) if (weapon != NULL)
{ {
weapon->DepleteAmmo (weapon->bAltFire, false); weapon->DepleteAmmo(weapon->bAltFire, false);
} }
} }
break; break;

View file

@ -336,7 +336,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
// [RH] Do some stuff to make this more useful outside Hexen // [RH] Do some stuff to make this more useful outside Hexen
if (self->flags4 & MF4_BOSSDEATH) if (self->flags4 & MF4_BOSSDEATH)
{ {
CALL_ACTION(A_BossDeath, self); A_BossDeath(self);
} }
A_Unblock(self, true); A_Unblock(self, true);

View file

@ -42,6 +42,18 @@ IMPLEMENT_CLASS (APowerup)
// Powerup-Giver ------------------------------------------------------------- // Powerup-Giver -------------------------------------------------------------
IMPLEMENT_CLASS(PClassPowerupGiver)
void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass)
{
Super::ReplaceClassRef(oldclass, newclass);
APowerupGiver *def = (APowerupGiver*)Defaults;
if (def != NULL)
{
if (def->PowerupType == oldclass) def->PowerupType = static_cast<PClassWeapon *>(newclass);
}
}
//=========================================================================== //===========================================================================
// //
// APowerupGiver :: Use // APowerupGiver :: Use

View file

@ -36,14 +36,24 @@ protected:
friend void InitAllPowerupEffects(AInventory *item); friend void InitAllPowerupEffects(AInventory *item);
}; };
class PClassPowerupGiver: public PClassInventory
{
DECLARE_CLASS(PClassPowerupGiver, PClassInventory)
protected:
public:
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
};
// An artifact is an item that gives the player a powerup when activated. // An artifact is an item that gives the player a powerup when activated.
class APowerupGiver : public AInventory class APowerupGiver : public AInventory
{ {
DECLARE_CLASS (APowerupGiver, AInventory) DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver)
public: public:
virtual bool Use (bool pickup); virtual bool Use (bool pickup);
virtual void Serialize (FArchive &arc); virtual void Serialize (FArchive &arc);
PClassActor *PowerupType; PClassActor *PowerupType;
int EffectTics; // Non-0 to override the powerup's default tics int EffectTics; // Non-0 to override the powerup's default tics
PalEntry BlendColor; // Non-0 to override the powerup's default blend PalEntry BlendColor; // Non-0 to override the powerup's default blend

View file

@ -550,10 +550,7 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
if (realme->flags4 & MF4_BOSSDEATH) if (realme->flags4 & MF4_BOSSDEATH)
{ {
realme->health = 0; // make sure that A_BossDeath considers it dead. realme->health = 0; // make sure that A_BossDeath considers it dead.
// FIXME: Use the caller's stack once the whole chain is scriptable. A_BossDeath(realme);
VMFrameStack stack;
VMValue params[3] = { realme, realme, VMValue(NULL, ATAG_STATE) };
stack.Call(A_BossDeath_VMPtr, params, countof(params), NULL, 0, NULL);
} }
} }
fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die() fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die()

View file

@ -1,5 +1,5 @@
// Ammo: Something a weapon needs to operate //
class PClassWeaponPiece : public PClassInventory class PClassWeaponPiece : public PClassInventory
{ {
DECLARE_CLASS(PClassWeaponPiece, PClassInventory) DECLARE_CLASS(PClassWeaponPiece, PClassInventory)

View file

@ -163,6 +163,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerDeath)
} }
} }
// the sky change scripts are now done as special actions in MAPINFO // the sky change scripts are now done as special actions in MAPINFO
CALL_ACTION(A_BossDeath, self); A_BossDeath(self);
return 0; return 0;
} }

View file

@ -61,6 +61,11 @@ FRandom FState::pr_statetics("StateTics");
cycle_t ActionCycles; cycle_t ActionCycles;
void FState::SetAction(const char *name)
{
ActionFunc = FindGlobalActionFunction(name)->Variants[0].Implementation;
}
bool FState::CallAction(AActor *self, AActor *stateowner) bool FState::CallAction(AActor *self, AActor *stateowner)
{ {
if (ActionFunc != NULL) if (ActionFunc != NULL)

View file

@ -126,6 +126,8 @@ struct FState
Frame = frame - 'A'; Frame = frame - 'A';
} }
void SetAction(VMFunction *func) { ActionFunc = func; } void SetAction(VMFunction *func) { ActionFunc = func; }
void ClearAction() { ActionFunc = NULL; }
void SetAction(const char *name);
bool CallAction(AActor *self, AActor *stateowner); bool CallAction(AActor *self, AActor *stateowner);
static PClassActor *StaticFindStateOwner (const FState *state); static PClassActor *StaticFindStateOwner (const FState *state);
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info); static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);

View file

@ -1043,58 +1043,58 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if ((rawdamage < TELEFRAG_DAMAGE) || (target->flags7 & MF7_LAXTELEFRAGDMG)) // TELEFRAG_DAMAGE may only be reduced with LAXTELEFRAGDMG or it may not guarantee its effect. if ((rawdamage < TELEFRAG_DAMAGE) || (target->flags7 & MF7_LAXTELEFRAGDMG)) // TELEFRAG_DAMAGE may only be reduced with LAXTELEFRAGDMG or it may not guarantee its effect.
{ {
if (player && damage > 1) if (player && damage > 1)
{
// Take half damage in trainer mode
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
}
// Special damage types
if (inflictor)
{
if (inflictor->flags4 & MF4_SPECTRAL)
{ {
if (player != NULL) // Take half damage in trainer mode
{ damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
if (!deathmatch && inflictor->FriendPlayer > 0)
return -1;
}
else if (target->flags4 & MF4_SPECTRAL)
{
if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
return -1;
}
} }
// Special damage types
if (inflictor)
{
if (inflictor->flags4 & MF4_SPECTRAL)
{
if (player != NULL)
{
if (!deathmatch && inflictor->FriendPlayer > 0)
return -1;
}
else if (target->flags4 & MF4_SPECTRAL)
{
if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
return -1;
}
}
damage = inflictor->DoSpecialDamage(target, damage, mod); damage = inflictor->DoSpecialDamage(target, damage, mod);
if (damage < 0) if (damage < 0)
{ {
return -1; return -1;
}
} }
}
int olddam = damage; int olddam = damage;
if (damage > 0 && source != NULL) if (damage > 0 && source != NULL)
{ {
damage = FixedMul(damage, source->DamageMultiply); damage = FixedMul(damage, source->DamageMultiply);
// Handle active damage modifiers (e.g. PowerDamage) // Handle active damage modifiers (e.g. PowerDamage)
if (damage > 0 && source->Inventory != NULL) if (damage > 0 && source->Inventory != NULL)
{ {
source->Inventory->ModifyDamage(damage, mod, damage, false); source->Inventory->ModifyDamage(damage, mod, damage, false);
}
} }
} // Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT)) if (damage > 0 && (target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
{ {
target->Inventory->ModifyDamage(damage, mod, damage, true); target->Inventory->ModifyDamage(damage, mod, damage, true);
} }
if (damage > 0 && !(flags & DMG_NO_FACTOR)) if (damage > 0 && !(flags & DMG_NO_FACTOR))
{
damage = FixedMul(damage, target->DamageFactor);
if (damage > 0)
{ {
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->DamageFactors); damage = FixedMul(damage, target->DamageFactor);
} if (damage > 0)
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->DamageFactors);
}
} }
if (damage >= 0) if (damage >= 0)
@ -1105,23 +1105,23 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// '<0' is handled below. This only handles the case where damage gets reduced to 0. // '<0' is handled below. This only handles the case where damage gets reduced to 0.
if (damage == 0 && olddam > 0) if (damage == 0 && olddam > 0)
{ {
{ // Still allow FORCEPAIN { // Still allow FORCEPAIN
if (forcedPain) if (forcedPain)
{ {
goto dopain; goto dopain;
} }
else if (fakedPain) else if (fakedPain)
{ {
goto fakepain; goto fakepain;
} }
return -1; return -1;
}
} }
} }
}
if (target->flags5 & MF5_NODAMAGE) if (target->flags5 & MF5_NODAMAGE)
{ {
damage = 0; damage = 0;
} }
} }
if (damage < 0) if (damage < 0)
{ {

View file

@ -620,7 +620,9 @@ bool AActor::SetState (FState *newstate, bool nofunction)
if (ObjectFlags & OF_StateChanged) if (ObjectFlags & OF_StateChanged)
{ // The action was an A_Jump-style function that wants to change the next state. { // The action was an A_Jump-style function that wants to change the next state.
ObjectFlags &= ~OF_StateChanged; ObjectFlags &= ~OF_StateChanged;
FState *saved = newstate;
newstate = state; newstate = state;
state = saved; // we need this for comparison of sprites.
tics = 0; // make sure we loop and set the new state properly tics = 0; // make sure we loop and set the new state properly
continue; continue;
} }

View file

@ -1,7 +1,11 @@
#ifndef OALDEF_H #ifndef OALDEF_H
#define OALDEF_H #define OALDEF_H
#if defined _WIN32 && !defined NO_OPENAL #ifndef NO_OPENAL
#ifndef _WIN32
typedef void* FARPROC;
#endif
#define DEFINE_ENTRY(type, name) static type p_##name; #define DEFINE_ENTRY(type, name) static type p_##name;
#include "oaldef.h" #include "oaldef.h"

View file

@ -36,6 +36,8 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#define USE_WINDOWS_DWORD #define USE_WINDOWS_DWORD
#else
#include <dlfcn.h>
#endif #endif
#include "except.h" #include "except.h"
@ -61,14 +63,23 @@ CVAR (Bool, snd_efx, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#ifdef _WIN32 #ifdef _WIN32
static HMODULE hmodOpenAL; static HMODULE hmodOpenAL;
#define OPENALLIB "openal32.dll"
#else
static void* hmodOpenAL;
#ifdef __APPLE__
#define OPENALLIB "OpenAL.framework/OpenAL"
#else
#define OPENALLIB "libopenal.so"
#endif
#define LoadLibrary(x) dlopen((x), RTLD_LAZY)
#define GetProcAddress(a,b) dlsym((a),(b))
#define FreeLibrary(x) dlclose((x))
#endif #endif
bool IsOpenALPresent() bool IsOpenALPresent()
{ {
#ifdef NO_OPENAL #ifdef NO_OPENAL
return false; return false;
#elif !defined _WIN32
return true;
#else #else
static bool cached_result = false; static bool cached_result = false;
static bool done = false; static bool done = false;
@ -78,10 +89,10 @@ bool IsOpenALPresent()
done = true; done = true;
if (hmodOpenAL == NULL) if (hmodOpenAL == NULL)
{ {
hmodOpenAL = LoadLibrary(NicePath("$PROGDIR/openal32.dll")); hmodOpenAL = LoadLibrary(NicePath("$PROGDIR/" OPENALLIB));
if (hmodOpenAL == NULL) if (hmodOpenAL == NULL)
{ {
hmodOpenAL = LoadLibrary("openal32.dll"); hmodOpenAL = LoadLibrary(OPENALLIB);
if (hmodOpenAL == NULL) if (hmodOpenAL == NULL)
{ {
return false; return false;
@ -90,7 +101,7 @@ bool IsOpenALPresent()
for(int i = 0; oalfuncs[i].name != NULL; i++) for(int i = 0; oalfuncs[i].name != NULL; i++)
{ {
*oalfuncs[i].funcaddr = GetProcAddress(hmodOpenAL, oalfuncs[i].name); *oalfuncs[i].funcaddr = GetProcAddress(hmodOpenAL, oalfuncs[i].name);
if (oalfuncs[i].funcaddr == NULL) if (*oalfuncs[i].funcaddr == NULL)
{ {
FreeLibrary(hmodOpenAL); FreeLibrary(hmodOpenAL);
hmodOpenAL = NULL; hmodOpenAL = NULL;
@ -1332,13 +1343,13 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
FVector3 dir = pos - listener->position; FVector3 dir = pos - listener->position;
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
{ {
float gain = GetRolloff(rolloff, sqrt(dist_sqr) * distscale); float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale);
dir.Resize((gain > 0.00001f) ? 1.f/gain : 100000.f); dir.Resize((gain > 0.00001f) ? 1.f/gain : 100000.f);
} }
if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{ {
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
float a = sqrt(dist_sqr) / AREA_SOUND_RADIUS; float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a; dir = amb + (dir-amb)*a;
} }
dir += listener->position; dir += listener->position;
@ -1351,7 +1362,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
float mindist = rolloff->MinDistance/distscale; float mindist = rolloff->MinDistance/distscale;
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
float a = sqrt(dist_sqr) / AREA_SOUND_RADIUS; float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a; dir = amb + (dir-amb)*a;
dir += listener->position; dir += listener->position;
@ -1571,13 +1582,13 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
{ {
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
{ {
float gain = GetRolloff(&chan->Rolloff, sqrt(chan->DistanceSqr) * chan->DistanceScale); float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale);
dir.Resize((gain > 0.00001f) ? 1.f/gain : 100000.f); dir.Resize((gain > 0.00001f) ? 1.f/gain : 100000.f);
} }
if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{ {
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
float a = sqrt(chan->DistanceSqr) / AREA_SOUND_RADIUS; float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a; dir = amb + (dir-amb)*a;
} }
} }
@ -1585,7 +1596,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
{ {
float mindist = chan->Rolloff.MinDistance / chan->DistanceScale; float mindist = chan->Rolloff.MinDistance / chan->DistanceScale;
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
float a = sqrt(chan->DistanceSqr) / AREA_SOUND_RADIUS; float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a; dir = amb + (dir-amb)*a;
} }
dir += listener->position; dir += listener->position;
@ -1606,9 +1617,9 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
float angle = listener->angle; float angle = listener->angle;
ALfloat orient[6]; ALfloat orient[6];
// forward // forward
orient[0] = cos(angle); orient[0] = cosf(angle);
orient[1] = 0.f; orient[1] = 0.f;
orient[2] = -sin(angle); orient[2] = -sinf(angle);
// up // up
orient[3] = 0.f; orient[3] = 0.f;
orient[4] = 1.f; orient[4] = 1.f;
@ -1747,7 +1758,7 @@ float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan)
alGetSourcef(source, AL_GAIN, &volume); alGetSourcef(source, AL_GAIN, &volume);
getALError(); getALError();
volume *= GetRolloff(&chan->Rolloff, sqrt(chan->DistanceSqr) * chan->DistanceScale); volume *= GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale);
return volume; return volume;
} }

View file

@ -234,24 +234,24 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{ {
if (extra.bExplosive) if (extra.bExplosive)
{ {
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Explode")->Variants[0].Implementation); type->OwnedStates[extra.DeathStart].SetAction("A_Explode");
} }
} }
else else
{ {
// The first frame plays the death sound and // The first frame plays the death sound and
// the second frame makes it nonsolid. // the second frame makes it nonsolid.
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Scream")->Variants[0].Implementation); type->OwnedStates[extra.DeathStart].SetAction("A_Scream");
if (extra.bSolidOnDeath) if (extra.bSolidOnDeath)
{ {
} }
else if (extra.DeathStart + 1 < extra.DeathEnd) else if (extra.DeathStart + 1 < extra.DeathEnd)
{ {
type->OwnedStates[extra.DeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Variants[0].Implementation); type->OwnedStates[extra.DeathStart+1].SetAction("A_NoBlocking");
} }
else else
{ {
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_ScreamAndUnblock")->Variants[0].Implementation); type->OwnedStates[extra.DeathStart].SetAction("A_ScreamAndUnblock");
} }
if (extra.DeathHeight == 0) if (extra.DeathHeight == 0)
@ -283,17 +283,17 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
// The first frame plays the burn sound and // The first frame plays the burn sound and
// the second frame makes it nonsolid. // the second frame makes it nonsolid.
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveSound")->Variants[0].Implementation); type->OwnedStates[extra.FireDeathStart].SetAction("A_ActiveSound");
if (extra.bSolidOnBurn) if (extra.bSolidOnBurn)
{ {
} }
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd) else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
{ {
type->OwnedStates[extra.FireDeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Variants[0].Implementation); type->OwnedStates[extra.FireDeathStart+1].SetAction("A_NoBlocking");
} }
else else
{ {
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveAndUnblock")->Variants[0].Implementation); type->OwnedStates[extra.FireDeathStart].SetAction("A_ActiveAndUnblock");
} }
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height; if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
@ -314,14 +314,14 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
type->OwnedStates[i].Tics = 5; type->OwnedStates[i].Tics = 5;
type->OwnedStates[i].TicRange = 0; type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0; type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeath")->Variants[0].Implementation); type->OwnedStates[i].SetAction("A_FreezeDeath");
i = type->NumOwnedStates - 1; i = type->NumOwnedStates - 1;
type->OwnedStates[i].NextState = &type->OwnedStates[i]; type->OwnedStates[i].NextState = &type->OwnedStates[i];
type->OwnedStates[i].Tics = 1; type->OwnedStates[i].Tics = 1;
type->OwnedStates[i].TicRange = 0; type->OwnedStates[i].TicRange = 0;
type->OwnedStates[i].Misc1 = 0; type->OwnedStates[i].Misc1 = 0;
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks")->Variants[0].Implementation); type->OwnedStates[i].SetAction("A_FreezeDeathChunks");
bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]); bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]);
} }
else if (extra.bGenericIceDeath) else if (extra.bGenericIceDeath)

View file

@ -3310,7 +3310,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
// [RH] Do some stuff to make this more useful outside Hexen // [RH] Do some stuff to make this more useful outside Hexen
if (self->flags4 & MF4_BOSSDEATH) if (self->flags4 & MF4_BOSSDEATH)
{ {
CALL_ACTION(A_BossDeath, self); A_BossDeath(self);
} }
A_Unblock(self, true); A_Unblock(self, true);
@ -6485,6 +6485,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
if (mo == ref) //Don't count self. if (mo == ref) //Don't count self.
continue; continue;
// no unmorphed versions of currently morphed players.
if (mo->flags & MF_UNMORPHED)
continue;
//Check inheritance for the classname. Taken partly from CheckClass DECORATE function. //Check inheritance for the classname. Taken partly from CheckClass DECORATE function.
if (flags & CPXF_ANCESTOR) if (flags & CPXF_ANCESTOR)
{ {

View file

@ -195,6 +195,7 @@ protected:
{ {
isresolved = false; isresolved = false;
ScriptPosition = pos; ScriptPosition = pos;
ValueType = VAL_Unresolved;
} }
public: public:
virtual ~FxExpression() {} virtual ~FxExpression() {}

View file

@ -623,7 +623,7 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build)
else else
{ {
assert(ValueType == VAL_Float); assert(ValueType == VAL_Float);
build->Emit(OP_NEG, from.RegNum, from.RegNum, 0); build->Emit(OP_FLOP, from.RegNum, from.RegNum, FLOP_NEG);
} }
return from; return from;
} }

View file

@ -88,17 +88,11 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
// Do automatic coercion between ints and floats. // Do automatic coercion between ints and floats.
if (type == TypeSInt32) if (type == TypeSInt32)
{ {
if (x->ValueType != VAL_Int) x = new FxIntCast(x);
{
x = new FxIntCast(x);
}
} }
else else
{ {
if (x->ValueType != VAL_Float) x = new FxFloatCast(x);
{
x = new FxFloatCast(x);
}
} }
} }
else if (type == TypeName || type == TypeString) else if (type == TypeName || type == TypeString)

View file

@ -8,6 +8,7 @@
enum ExpValType enum ExpValType
{ {
VAL_Unresolved, // type not yet known
VAL_Int, // integer number VAL_Int, // integer number
VAL_Float, // floating point number VAL_Float, // floating point number
VAL_Unknown, // nothing VAL_Unknown, // nothing

View file

@ -231,7 +231,7 @@ ACTOR Actor native //: Thinker
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT);
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
action native A_RadiusGive(class<Inventory> itemtype, int distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", int mindist = 0); action native A_RadiusGive(class<Inventory> itemtype, float distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", int mindist = 0);
action native A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); action native A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT);
action native A_CountdownArg(int argnum, state targstate = ""); action native A_CountdownArg(int argnum, state targstate = "");
action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);