This commit is contained in:
Christoph Oelckers 2014-12-21 13:49:23 +01:00
commit 58a3b86813
16 changed files with 377 additions and 80 deletions

View file

@ -983,6 +983,8 @@ public:
FNameNoInit PainType;
FNameNoInit DeathType;
const PClass *TeleFogSourceType;
const PClass *TeleFogDestType;
FState *SpawnState;
FState *SeeState;

View file

@ -152,23 +152,33 @@ IOKitJoystick::IOKitJoystick( IOHIDDeviceRef device )
: m_device( device )
, m_sensitivity( DEFAULT_SENSITIVITY )
{
IOHIDElementRef element = HIDGetFirstDeviceElement( device, kHIDElementTypeInput );
while ( NULL != element )
assert(NULL != device);
assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device));
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
assert(NULL != elements);
assert(CFArrayGetTypeID() == CFGetTypeID(elements));
for (CFIndex i = 0, count = CFArrayGetCount(elements); i < count; ++i)
{
const IOHIDElementRef element =
static_cast<IOHIDElementRef>(const_cast<void*>(CFArrayGetValueAtIndex(elements, i)));
assert(NULL != element);
assert(IOHIDElementGetTypeID() == CFGetTypeID(element));
const uint32_t usagePage = IOHIDElementGetUsagePage( element );
if ( kHIDPage_GenericDesktop == usagePage )
{
const uint32_t usage = IOHIDElementGetUsage( element );
if ( kHIDUsage_GD_Slider == usage
if ( kHIDUsage_GD_Slider == usage
|| kHIDUsage_GD_X == usage || kHIDUsage_GD_Y == usage || kHIDUsage_GD_Z == usage
|| kHIDUsage_GD_Rx == usage || kHIDUsage_GD_Ry == usage || kHIDUsage_GD_Rz == usage )
{
AxisInfo axis;
memset( &axis, 0, sizeof( axis ) );
if ( const CFStringRef name = IOHIDElementGetName( element ) )
{
CFStringGetCString( name, axis.name, sizeof( axis.name ) - 1, kCFStringEncodingUTF8 );
@ -177,22 +187,22 @@ IOKitJoystick::IOKitJoystick( IOHIDDeviceRef device )
{
snprintf( axis.name, sizeof( axis.name ), "Axis %i", m_axes.Size() + 1 );
}
axis.element = element;
m_axes.Push( axis );
IOHIDElement_SetCalibrationMin( element, -1 );
IOHIDElement_SetCalibrationMax( element, 1 );
HIDQueueElement( m_device, element );
}
else if ( kHIDUsage_GD_Hatswitch == usage && m_POVs.Size() < 4 )
{
m_POVs.Push( element );
HIDQueueElement( m_device, element );
}
}
}
else if ( kHIDPage_Button == usagePage )
{
@ -200,10 +210,10 @@ IOKitJoystick::IOKitJoystick( IOHIDDeviceRef device )
HIDQueueElement( m_device, element );
}
element = HIDGetNextDeviceElement( element, kHIDElementTypeInput );
}
CFRelease(elements);
SetDefaultConfig();
}

View file

@ -109,6 +109,7 @@ enum SAW_Flags
SF_NOUSEAMMO = 16,
SF_NOPULLIN = 32,
SF_NOTURN = 64,
SF_STEALARMOR = 128,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
@ -119,7 +120,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
AActor *linetarget;
int actualdamage;
ACTION_PARAM_START(9);
ACTION_PARAM_START(11);
ACTION_PARAM_SOUND(fullsound, 0);
ACTION_PARAM_SOUND(hitsound, 1);
ACTION_PARAM_INT(damage, 2);
@ -129,6 +130,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
ACTION_PARAM_ANGLE(Spread_XY, 6);
ACTION_PARAM_ANGLE(Spread_Z, 7);
ACTION_PARAM_FIXED(LifeSteal, 8);
ACTION_PARAM_INT(lifestealmax, 9);
ACTION_PARAM_CLASS(armorbonustype, 10);
if (NULL == (player = self->player))
{
@ -184,7 +187,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
}
if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN))
P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS);
{
if (Flags & SF_STEALARMOR)
{
if (!armorbonustype) armorbonustype = PClass::FindClass("ArmorBonus");
if (armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn (armorbonustype, 0,0,0, NO_REPLACE));
armorbonus->SaveAmount *= (actualdamage * LifeSteal) >> FRACBITS;
armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
armorbonus->flags |= MF_DROPPED;
armorbonus->ClearCounters();
if (!armorbonus->CallTryPickup (self))
{
armorbonus->Destroy ();
}
}
}
else
{
P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS, lifestealmax);
}
}
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);

View file

@ -4438,6 +4438,8 @@ enum EACSFunctions
ACSF_PickActor,
ACSF_IsPointerEqual,
ACSF_CanRaiseActor,
ACSF_SetActorTeleFog, // 86
ACSF_SwapActorTeleFog,
/* Zandronum's - these must be skipped when we reach 99!
-100:ResetMap(0),
@ -4749,6 +4751,82 @@ static void SetActorPitch(AActor *activator, int tid, int angle, bool interpolat
}
}
static void SetActorTeleFog(AActor *activator, int tid, FName telefogsrc, FName telefogdest)
{
//Simply put, if it doesn't exist, it won't change. One can use "" in this scenario.
const PClass *check;
if (tid == 0)
{
if (activator != NULL)
{
check = PClass::FindClass(telefogsrc);
if (check == NULL || !stricmp(telefogsrc, "none") || !stricmp(telefogsrc, "null"))
activator->TeleFogSourceType = NULL;
else
activator->TeleFogSourceType = check;
check = PClass::FindClass(telefogdest);
if (check == NULL || !stricmp(telefogdest, "none") || !stricmp(telefogdest, "null"))
activator->TeleFogDestType = NULL;
else
activator->TeleFogDestType = check;
}
}
else
{
FActorIterator iterator(tid);
AActor *actor;
while ((actor = iterator.Next()))
{
check = PClass::FindClass(telefogsrc);
if (check == NULL || !stricmp(telefogsrc, "none") || !stricmp(telefogsrc, "null"))
actor->TeleFogSourceType = NULL;
else
actor->TeleFogSourceType = check;
check = PClass::FindClass(telefogdest);
if (check == NULL || !stricmp(telefogdest, "none") || !stricmp(telefogdest, "null"))
actor->TeleFogDestType = NULL;
else
actor->TeleFogDestType = check;
}
}
}
static int SwapActorTeleFog(AActor *activator, int tid)
{
int count = 0;
if (tid == 0)
{
if ((activator == NULL) || (activator->TeleFogSourceType = activator->TeleFogDestType))
return 0; //Does nothing if they're the same.
else
{
const PClass *temp = activator->TeleFogSourceType;
activator->TeleFogSourceType = activator->TeleFogDestType;
activator->TeleFogDestType = temp;
return 1;
}
}
else
{
FActorIterator iterator(tid);
AActor *actor;
while ((actor = iterator.Next()))
{
if (actor->TeleFogSourceType == actor->TeleFogDestType)
continue; //They're the same. Save the effort.
const PClass *temp = actor->TeleFogSourceType;
actor->TeleFogSourceType = actor->TeleFogDestType;
actor->TeleFogDestType = temp;
count++;
}
}
return count;
}
int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth)
@ -5662,7 +5740,18 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false);
}
break;
case ACSF_SetActorTeleFog:
if (argCount >= 3)
{
SetActorTeleFog(activator, args[0], FBehavior::StaticLookupString(args[1]), FBehavior::StaticLookupString(args[2]));
}
break;
case ACSF_SwapActorTeleFog:
if (argCount >= 1)
{
return SwapActorTeleFog(activator, args[0]);
}
break;
case ACSF_PickActor:
if (argCount >= 5)
{

View file

@ -3003,6 +3003,10 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
{
if (mo->bouncecount > 0 && --mo->bouncecount == 0) return false;
if (mo->flags7 & MF7_HITTARGET) mo->target = BlockingMobj;
if (mo->flags7 & MF7_HITMASTER) mo->master = BlockingMobj;
if (mo->flags7 & MF7_HITTRACER) mo->tracer = BlockingMobj;
if (!ontop)
{
fixed_t speed;
@ -3746,6 +3750,8 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
hity = t1->y + FixedMul(vy, dist);
hitz = shootz + FixedMul(vz, dist);
// Spawn bullet puffs or blood spots, depending on target type.
if ((puffDefaults != NULL && puffDefaults->flags3 & MF3_PUFFONACTORS) ||
(trace.Actor->flags & MF_NOBLOOD) ||
@ -3758,6 +3764,13 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
puff = P_SpawnPuff(t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags | PF_HITTHING);
}
if (puffDefaults != NULL && trace.Actor != NULL && puff != NULL)
{
if (puffDefaults->flags7 && MF7_HITTARGET) puff->target = trace.Actor;
if (puffDefaults->flags7 && MF7_HITMASTER) puff->master = trace.Actor;
if (puffDefaults->flags7 && MF7_HITTRACER) puff->tracer = trace.Actor;
}
// Allow puffs to inflict poison damage, so that hitscans can poison, too.
if (puffDefaults != NULL && puffDefaults->PoisonDamage > 0 && puffDefaults->PoisonDuration != INT_MIN)
{
@ -3776,7 +3789,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
{
dmgflags |= DMG_NO_ARMOR;
}
if (puff == NULL)
{
// Since the puff is the damage inflictor we need it here
@ -4150,7 +4163,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
int flags;
assert(puffclass != NULL); // Because we set it to a default above
AActor *puffDefaults = GetDefaultByType(puffclass->GetReplacement());
AActor *puffDefaults = GetDefaultByType(puffclass->GetReplacement()); //Contains all the flags such as FOILINVUL, etc.
flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? 0 : TRACE_PCross | TRACE_Impact;
rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true;
@ -4200,6 +4213,12 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
{
P_SpawnPuff(source, puffclass, x, y, z, (source->angle + angleoffset) - ANG90, 1, puffflags);
}
if (hitactor != NULL && puffDefaults != NULL && thepuff != NULL)
{
if (puffDefaults->flags7 & MF7_HITTARGET) thepuff->target = hitactor;
if (puffDefaults->flags7 & MF7_HITMASTER) thepuff->master = hitactor;
if (puffDefaults->flags7 & MF7_HITTRACER) thepuff->tracer = hitactor;
}
if (puffDefaults && puffDefaults->PoisonDamage > 0 && puffDefaults->PoisonDuration != INT_MIN)
{
P_PoisonMobj(hitactor, thepuff ? thepuff : source, source, puffDefaults->PoisonDamage, puffDefaults->PoisonDuration, puffDefaults->PoisonPeriod, puffDefaults->PoisonDamageType);
@ -4208,6 +4227,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
dmgFlagPass += (puffDefaults->flags3 & MF3_FOILINVUL) ? DMG_FOILINVUL : 0; //[MC]Because the original foilinvul check wasn't working.
dmgFlagPass += (puffDefaults->flags7 & MF7_FOILBUDDHA) ? DMG_FOILBUDDHA : 0;
int newdam = P_DamageMobj(hitactor, thepuff ? thepuff : source, source, damage, damagetype, dmgFlagPass);
if (bleed)
{
P_SpawnBlood(x, y, z, (source->angle + angleoffset) - ANG180, newdam > 0 ? newdam : damage, hitactor);

View file

@ -333,7 +333,11 @@ void AActor::Serialize (FArchive &arc)
{
arc << FriendPlayer;
}
if (SaveVersion >= 4517)
{
arc << TeleFogSourceType
<< TeleFogDestType;
}
{
FString tagstr;
if (arc.IsStoring() && Tag != NULL && Tag->Len() > 0) tagstr = *Tag;
@ -2680,18 +2684,10 @@ void P_NightmareRespawn (AActor *mobj)
mo->PrevZ = z; // Do not interpolate Z position if we changed it since spawning.
// spawn a teleport fog at old spot because of removal of the body?
mo = Spawn ("TeleportFog", mobj->x, mobj->y, mobj->z, ALLOW_REPLACE);
if (mo != NULL)
{
mo->z += TELEFOGHEIGHT;
}
P_SpawnTeleportFog(mobj, mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, true);
// spawn a teleport fog at the new spot
mo = Spawn ("TeleportFog", x, y, z, ALLOW_REPLACE);
if (mo != NULL)
{
mo->z += TELEFOGHEIGHT;
}
P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false);
// remove the old monster
mobj->Destroy ();

View file

@ -903,6 +903,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag);
//
// P_TELEPT
//
void P_SpawnTeleportFog(AActor *mobj, fixed_t x, fixed_t y, fixed_t z, bool beforeTele = true, bool setTarget = false); //Spawns teleport fog. Pass the actor to pluck TeleFogFromType and TeleFogToType. 'from' determines if this is the fog to spawn at the old position (true) or new (false).
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false);
bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false);
bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse);

View file

@ -74,19 +74,22 @@ void ATeleportFog::PostBeginPlay ()
//
//==========================================================================
void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid)
void P_SpawnTeleportFog(AActor *mobj, fixed_t x, fixed_t y, fixed_t z, bool beforeTele, bool setTarget)
{
const PClass *fog = P_GetSpawnableType(spawnid);
if (fog == NULL)
AActor *mo;
if ((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType) == NULL)
{
AActor *mo = Spawn ("TeleportFog", x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE);
//Do nothing.
mo = NULL;
}
else
{
AActor *mo = Spawn (fog, x, y, z, ALLOW_REPLACE);
if (mo != NULL) S_Sound(mo, CHAN_BODY, mo->SeeSound, 1.f, ATTN_NORM);
mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), x, y, z, ALLOW_REPLACE);
}
if (mo != NULL && setTarget)
mo->target = mobj;
}
//
@ -186,8 +189,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
if (sourceFog && !predicting)
{
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE);
fog->target = thing;
P_SpawnTeleportFog(thing, oldx, oldy, oldz, true, true); //Passes the actor through which then pulls the TeleFog metadate types based on properties.
}
if (useFog)
{
@ -195,9 +197,8 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
{
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
an = angle >> ANGLETOFINESHIFT;
AActor *fog = Spawn<ATeleportFog>(x + 20 * finecosine[an],
y + 20 * finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
fog->target = thing;
P_SpawnTeleportFog(thing, x + 20 * finecosine[an], y + 20 * finesine[an], thing->z + fogDelta, false, true);
}
if (thing->player)
{

View file

@ -92,7 +92,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog,
mobj->angle = (angle != ANGLE_MAX ? angle : spot->angle);
if (fog)
{
Spawn<ATeleportFog> (spot->x, spot->y, spot->z + TELEFOGHEIGHT, ALLOW_REPLACE);
P_SpawnTeleportFog(mobj, spot->x, spot->y, spot->z + TELEFOGHEIGHT, false);
}
if (mobj->flags & MF_SPECIAL)
mobj->flags |= MF_DROPPED; // Don't respawn
@ -130,8 +130,8 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog)
{
if (fog)
{
Spawn<ATeleportFog> (x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE);
Spawn<ATeleportFog> (oldx, oldy, oldz + TELEFOGHEIGHT, ALLOW_REPLACE);
P_SpawnTeleportFog(source, x, y, z);
P_SpawnTeleportFog(source, oldx, oldy, oldz, false);
}
source->PrevX = x;
source->PrevY = y;

View file

@ -1385,17 +1385,20 @@ enum
CPF_PULLIN = 4,
CPF_NORANDOMPUFFZ = 8,
CPF_NOTURN = 16,
CPF_STEALARMOR = 32,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
{
ACTION_PARAM_START(5);
ACTION_PARAM_START(8);
ACTION_PARAM_INT(Damage, 0);
ACTION_PARAM_BOOL(norandom, 1);
ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_CLASS(PuffType, 3);
ACTION_PARAM_FIXED(Range, 4);
ACTION_PARAM_FIXED(LifeSteal, 5);
ACTION_PARAM_INT(lifestealmax, 6);
ACTION_PARAM_CLASS(armorbonustype, 7);
if (!self->player) return;
@ -1428,7 +1431,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
if (linetarget)
{
if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN))
P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS);
{
if (flags & CPF_STEALARMOR)
{
if (!armorbonustype) armorbonustype = PClass::FindClass("ArmorBonus");
if (armorbonustype->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
{
ABasicArmorBonus *armorbonus = static_cast<ABasicArmorBonus *>(Spawn (armorbonustype, 0,0,0, NO_REPLACE));
armorbonus->SaveAmount *= (actualdamage * LifeSteal) >> FRACBITS;
armorbonus->MaxSaveAmount = lifestealmax <= 0 ? armorbonus->MaxSaveAmount : lifestealmax;
armorbonus->flags |= MF_DROPPED;
armorbonus->ClearCounters();
if (!armorbonus->CallTryPickup (self))
{
armorbonus->Destroy ();
}
}
}
else
{
P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS, lifestealmax);
}
}
if (weapon != NULL)
{
@ -2938,9 +2965,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
{
ACTION_PARAM_START(1);
ACTION_PARAM_INT(flags, 0);
bool oktorespawn = false;
fixed_t oldx = self->x;
fixed_t oldy = self->y;
fixed_t oldz = self->z;
self->flags |= MF_SOLID;
self->height = self->GetDefault()->height;
CALL_ACTION(A_RestoreSpecialPosition, self);
@ -2998,7 +3026,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
if (flags & RSF_FOG)
{
Spawn<ATeleportFog> (self->x, self->y, self->z + TELEFOGHEIGHT, ALLOW_REPLACE);
P_SpawnTeleportFog(self, oldx, oldy, oldz, true);
P_SpawnTeleportFog(self, self->x, self->y, self->z, false);
}
if (self->CountsAsKill())
{
@ -4119,9 +4148,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
//===========================================================================
enum T_Flags
{
TF_TELEFRAG = 1, // Allow telefrag in order to teleport.
TF_RANDOMDECIDE = 2, // Randomly fail based on health. (A_Srcr2Decide)
TF_FORCED = 4, // Forget what's in the way. TF_Telefrag takes precedence though.
TF_TELEFRAG = 0x00000001, // Allow telefrag in order to teleport.
TF_RANDOMDECIDE = 0x00000002, // Randomly fail based on health. (A_Srcr2Decide)
TF_FORCED = 0x00000004, // Forget what's in the way. TF_Telefrag takes precedence though.
TF_KEEPVELOCITY = 0x00000008, // Preserve velocity.
TF_KEEPANGLE = 0x00000010, // Keep angle.
TF_USESPOTZ = 0x00000020, // Set the z to the spot's z, instead of the floor.
TF_NOSRCFOG = 0x00000040, // Don't leave any fog behind when teleporting.
TF_NODESTFOG = 0x00000080, // Don't spawn any fog at the arrival position.
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
@ -4152,14 +4188,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
if (pr_teleport() >= chance[chanceindex]) return;
}
if (TeleportState == NULL)
{
// Default to Teleport.
TeleportState = self->FindState("Teleport");
// If still nothing, then return.
if (!TeleportState) return;
}
DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return;
@ -4171,34 +4199,66 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
fixed_t prevX = self->x;
fixed_t prevY = self->y;
fixed_t prevZ = self->z;
bool teleResult = false;
//Take precedence and cooperate with telefragging first.
if (P_TeleportMove(self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG))
teleResult = true;
bool teleResult = P_TeleportMove(self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG);
if ((!(teleResult)) && (Flags & TF_FORCED))
{
//If for some reason the original move didn't work, regardless of telefrag, force it to move.
self->SetOrigin(spot->x, spot->y, spot->z);
teleResult = true;
}
if (teleResult)
{
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (FogType)
{
Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE);
//If a fog type is defined in the parameter, or the user wants to use the actor's predefined fogs,
//and if there's no desire to be fogless, spawn a fog based upon settings.
if (FogType || (Flags & TF_USEACTORFOG))
{
if (!(Flags & TF_NOSRCFOG))
{
if (Flags & TF_USEACTORFOG)
P_SpawnTeleportFog(self, prevX, prevY, prevZ, true);
else
Spawn(FogType, prevX, prevY, prevZ, ALLOW_REPLACE);
}
if (!(Flags & TF_NODESTFOG))
{
if (Flags & TF_USEACTORFOG)
P_SpawnTeleportFog(self, self->x, self->y, self->z, false);
else
Spawn(FogType, self->x, self->y, self->z, ALLOW_REPLACE);
}
}
if (Flags & TF_USESPOTZ)
self->z = spot->z;
else
self->z = self->floorz;
ACTION_JUMP(TeleportState);
if (!(Flags & TF_KEEPANGLE))
self->angle = spot->angle;
self->z = self->floorz;
self->angle = spot->angle;
self->velx = self->vely = self->velz = 0;
if (!(Flags & TF_KEEPVELOCITY))
self->velx = self->vely = self->velz = 0;
if (!(Flags & TF_NOJUMP))
{
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (TeleportState == NULL)
{
// Default to Teleport.
TeleportState = self->FindState("Teleport");
// If still nothing, then return.
if (!TeleportState) return;
}
ACTION_JUMP(TeleportState);
return;
}
}
ACTION_SET_RESULT(teleResult);
}
//===========================================================================
@ -5377,3 +5437,53 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove)
}
}
//===========================================================================
//
// A_SetTeleFog
//
// Sets the teleport fog(s) for the calling actor.
// Takes a name of the classes for te source and destination.
// Can set both at the same time. Use "" to retain the previous fog without
// changing it.
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTeleFog)
{
ACTION_PARAM_START(2);
ACTION_PARAM_NAME(oldpos, 0);
ACTION_PARAM_NAME(newpos, 1);
const PClass *check = PClass::FindClass(oldpos);
if (check == NULL || !stricmp(oldpos, "none") || !stricmp(oldpos, "null"))
self->TeleFogSourceType = NULL;
else if (!stricmp(oldpos, ""))
{ //Don't change it if it's just ""
}
else
self->TeleFogSourceType = check;
check = PClass::FindClass(newpos);
if (check == NULL || !stricmp(newpos, "none") || !stricmp(newpos, "null"))
self->TeleFogDestType = NULL;
else if (!stricmp(newpos, ""))
{ //Don't change it if it's just ""
}
else
self->TeleFogDestType = check;
}
//===========================================================================
//
// A_SwapTeleFog
//
// Switches the source and dest telefogs around.
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_SwapTeleFog)
{
if ((self->TeleFogSourceType != self->TeleFogDestType)) //Does nothing if they're the same.
{
const PClass *temp = self->TeleFogSourceType;
self->TeleFogSourceType = self->TeleFogDestType;
self->TeleFogDestType = temp;
}
}

View file

@ -1416,6 +1416,26 @@ DEFINE_PROPERTY(stamina, I, Actor)
defaults->stamina = i;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(telefogsourcetype, S, Actor)
{
PROP_STRING_PARM(str, 0);
if (!stricmp(str, "") || (!stricmp(str, "none")) || (!stricmp(str, "null")) || *str == 0) defaults->TeleFogSourceType = NULL;
else defaults->TeleFogSourceType = FindClassTentative(str,"TeleportFog");
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(telefogdesttype, S, Actor)
{
PROP_STRING_PARM(str, 0);
if (!stricmp(str, "") || (!stricmp(str, "none")) || (!stricmp(str, "null")) || *str == 0) defaults->TeleFogDestType = NULL;
else defaults->TeleFogDestType = FindClassTentative(str, "TeleportFog");
}
//==========================================================================
//
// Special inventory properties

View file

@ -76,7 +76,7 @@ const char *GetVersionString();
// Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got.
#define SAVEVER 4516
#define SAVEVER 4517
#define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

View file

@ -26,6 +26,8 @@ ACTOR Actor native //: Thinker
DesignatedTeam 255
PainType Normal
DeathType Normal
TeleFogSourceType "TeleportFog"
TeleFogDestType "TeleportFog"
// Variables for the expression evaluator
// NOTE: fixed_t and angle_t are only used here to ensure proper conversion
@ -317,6 +319,8 @@ ACTOR Actor native //: Thinker
action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0);
action native A_SetTeleFog(name oldpos, name newpos);
action native A_SwapTeleFog();
action native A_CheckSightOrRange(float distance, state label);
action native A_CheckRange(float distance, state label);

View file

@ -16,6 +16,7 @@ const int SF_NOUSEAMMOMISS = 8;
const int SF_NOUSEAMMO = 16;
const int SF_NOPULLIN = 32;
const int SF_NOTURN = 64;
const int SF_STEALARMOR = 128;
// Flags for A_CustomMissile
const int CMF_AIMOFFSET = 1;
@ -176,15 +177,29 @@ const int CPF_DAGGER = 2;
const int CPF_PULLIN = 4;
const int CPF_NORANDOMPUFFZ = 8;
const int CPF_NOTURN = 16;
const int CPF_STEALARMOR = 32;
// Flags for A_CustomMissile
const int FPF_AIMATANGLE = 1;
const int FPF_TRANSFERTRANSLATION = 2;
// Flags for A_Teleport
const int TF_TELEFRAG = 1;
const int TF_RANDOMDECIDE = 2;
const int TF_FORCED = 4;
enum
{
TF_TELEFRAG = 0x00000001, // Allow telefrag in order to teleport.
TF_RANDOMDECIDE = 0x00000002, // Randomly fail based on health. (A_Srcr2Decide)
TF_FORCED = 0x00000004, // Forget what's in the way. TF_Telefrag takes precedence though.
TF_KEEPVELOCITY = 0x00000008, // Preserve velocity.
TF_KEEPANGLE = 0x00000010, // Keep angle.
TF_USESPOTZ = 0x00000020, // Set the z to the spot's z, instead of the floor.
TF_NOSRCFOG = 0x00000040, // Don't leave any fog behind when teleporting.
TF_NODESTFOG = 0x00000080, // Don't spawn any fog at the arrival position.
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
TF_KEEPORIENTATION = TF_KEEPVELOCITY|TF_KEEPANGLE,
TF_NOFOG = TF_NOSRCFOG|TF_NODESTFOG,
};
// Flags for A_WolfAttack
const int WAF_NORANDOM = 1;

View file

@ -8,7 +8,7 @@ ACTOR Inventory native
Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"
action native A_JumpIfNoAmmo(state label);
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0);
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0);
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0);
@ -41,7 +41,7 @@ ACTOR Inventory native
action native A_ClearReFire();
action native A_CheckReload();
action native A_GunFlash(state flash = "", int flags = 0);
action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class<Actor> pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0);
action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class<Actor> pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
action native A_CheckForReload(int counter, state label, bool dontincrement = false);
action native A_ResetReloadCounter();
action native A_RestoreSpecialPosition();

View file

@ -665,6 +665,7 @@ OptionMenu "VideoOptions"
Slider "Screen size", "screenblocks", 3.0, 12.0, 1.0, 0
Slider "Brightness", "Gamma", 0.75, 3.0, 0.05, 2
Option "Vertical Sync", "vid_vsync", "OnOff"
Option "Rendering Interpolation", "cl_capfps", "OffOn"
Option "Column render mode", "r_columnmethod", "ColumnMethods"
StaticText " "
@ -685,6 +686,7 @@ OptionMenu "VideoOptions"
Option "Blood Type", "cl_bloodtype", "BloodTypes"
Option "Bullet Puff Type", "cl_pufftype", "PuffTypes"
Slider "Number of particles", "r_maxparticles", 100, 10000, 100, 0
Slider "Number of decals", "cl_maxdecals", 0, 10000, 100, 0
Option "Show player sprites", "r_drawplayersprites", "OnOff"
Option "Death camera", "r_deathcamera", "OnOff"
Option "Teleporter zoom", "telezoom", "OnOff"