mirror of https://github.com/ZDoom/qzdoom.git
Merge branch 'master' into scripting
Conflicts: src/actor.h src/dobject.h src/dobjgc.cpp src/p_local.h src/thingdef/thingdef_codeptr.cpp
This commit is contained in:
commit
9744b9e0d9
|
@ -276,12 +276,12 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU
|
||||||
return oldPtr;
|
return oldPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
|
#define SUCCESSOR(p) ((CPpmd_Void_Ref)(size_t)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
|
||||||
|
|
||||||
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||||
{
|
{
|
||||||
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
|
(p)->SuccessorLow = (UInt16)((UInt32)((size_t)v) & 0xFFFF);
|
||||||
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
(p)->SuccessorHigh = (UInt16)(((UInt32)((size_t)v) >> 16) & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RestartModel(CPpmd7 *p)
|
static void RestartModel(CPpmd7 *p)
|
||||||
|
|
|
@ -854,7 +854,7 @@ public:
|
||||||
bool intersects(AActor *other) const
|
bool intersects(AActor *other) const
|
||||||
{
|
{
|
||||||
fixed_t blockdist = radius + other->radius;
|
fixed_t blockdist = radius + other->radius;
|
||||||
return ( abs(X() - other->Y()) < blockdist && abs(Y() - other->Y()) < blockdist);
|
return ( abs(X() - other->X()) < blockdist && abs(Y() - other->Y()) < blockdist);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'absolute' is reserved for a linked portal implementation which needs
|
// 'absolute' is reserved for a linked portal implementation which needs
|
||||||
|
|
|
@ -353,6 +353,7 @@ static void MarkRoot()
|
||||||
SectorMarker->SecNum = 0;
|
SectorMarker->SecNum = 0;
|
||||||
}
|
}
|
||||||
Mark(SectorMarker);
|
Mark(SectorMarker);
|
||||||
|
Mark(interpolator.Head);
|
||||||
// Mark action functions
|
// Mark action functions
|
||||||
if (!FinalGC)
|
if (!FinalGC)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
#include "decallib.h"
|
#include "decallib.h"
|
||||||
#include "p_terrain.h"
|
#include "p_terrain.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "p_effect.h"
|
||||||
|
|
||||||
#include "g_shared/a_pickups.h"
|
#include "g_shared/a_pickups.h"
|
||||||
|
|
||||||
|
@ -4463,6 +4464,7 @@ enum EACSFunctions
|
||||||
ACSF_GetMaxInventory,
|
ACSF_GetMaxInventory,
|
||||||
ACSF_SetSectorDamage,
|
ACSF_SetSectorDamage,
|
||||||
ACSF_SetSectorTerrain,
|
ACSF_SetSectorTerrain,
|
||||||
|
ACSF_SpawnParticle,
|
||||||
|
|
||||||
/* Zandronum's - these must be skipped when we reach 99!
|
/* Zandronum's - these must be skipped when we reach 99!
|
||||||
-100:ResetMap(0),
|
-100:ResetMap(0),
|
||||||
|
@ -5981,6 +5983,34 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ACSF_SpawnParticle:
|
||||||
|
{
|
||||||
|
fixed_t x = args[0];
|
||||||
|
fixed_t y = args[1];
|
||||||
|
fixed_t z = args[2];
|
||||||
|
fixed_t xvel = args[3];
|
||||||
|
fixed_t yvel = args[4];
|
||||||
|
fixed_t zvel = args[5];
|
||||||
|
PalEntry color = args[6];
|
||||||
|
int lifetime = args[7];
|
||||||
|
bool fullbright = argCount > 8 ? !!args[8] : false;
|
||||||
|
int startalpha = argCount > 9 ? args[9] : 0xFF; // Byte trans
|
||||||
|
int size = argCount > 10 ? args[10] : 1;
|
||||||
|
int fadestep = argCount > 11 ? args[11] : -1;
|
||||||
|
fixed_t accelx = argCount > 12 ? args[12] : 0;
|
||||||
|
fixed_t accely = argCount > 13 ? args[13] : 0;
|
||||||
|
fixed_t accelz = argCount > 14 ? args[14] : 0;
|
||||||
|
|
||||||
|
startalpha = clamp<int>(startalpha, 0, 0xFF); // Clamp to byte
|
||||||
|
lifetime = clamp<int>(lifetime, 0, 0xFF); // Clamp to byte
|
||||||
|
fadestep = clamp<int>(fadestep, -1, 0xFF); // Clamp to byte inc. -1 (indicating automatic)
|
||||||
|
size = clamp<int>(size, 0, 0xFF); // Clamp to byte
|
||||||
|
|
||||||
|
if (lifetime != 0)
|
||||||
|
P_SpawnParticle(x, y, z, xvel, yvel, zvel, color, fullbright, startalpha, lifetime, size, fadestep, accelx, accely, accelz);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1345,12 +1345,15 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
||||||
if (reply->NextNode != 0)
|
if (reply->NextNode != 0)
|
||||||
{
|
{
|
||||||
int rootnode = npc->ConversationRoot;
|
int rootnode = npc->ConversationRoot;
|
||||||
unsigned next = (unsigned)(rootnode + (reply->NextNode < 0 ? -1 : 1) * reply->NextNode - 1);
|
const bool isNegative = reply->NextNode < 0;
|
||||||
|
const unsigned next = (unsigned)(rootnode + (isNegative ? -1 : 1) * reply->NextNode - 1);
|
||||||
|
|
||||||
if (next < StrifeDialogues.Size())
|
if (next < StrifeDialogues.Size())
|
||||||
{
|
{
|
||||||
npc->Conversation = StrifeDialogues[next];
|
npc->Conversation = StrifeDialogues[next];
|
||||||
|
|
||||||
|
if (isNegative)
|
||||||
|
{
|
||||||
if (gameaction != ga_slideshow)
|
if (gameaction != ga_slideshow)
|
||||||
{
|
{
|
||||||
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
||||||
|
@ -1362,6 +1365,11 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf ("Next node %u is invalid, no such dialog page\n", next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
npc->angle = player->ConversationNPCAngle;
|
npc->angle = player->ConversationNPCAngle;
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,31 @@ void P_ThinkParticles ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t velx, fixed_t vely, fixed_t velz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, BYTE size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz)
|
||||||
|
{
|
||||||
|
particle_t *particle = NewParticle();
|
||||||
|
|
||||||
|
if (particle)
|
||||||
|
{
|
||||||
|
particle->x = x;
|
||||||
|
particle->y = y;
|
||||||
|
particle->z = z;
|
||||||
|
particle->velx = velx;
|
||||||
|
particle->vely = vely;
|
||||||
|
particle->velz = velz;
|
||||||
|
particle->color = ParticleColor(color);
|
||||||
|
particle->trans = startalpha;
|
||||||
|
if (fadestep < 0) fadestep = FADEFROMTTL(lifetime);
|
||||||
|
particle->fade = fadestep;
|
||||||
|
particle->ttl = lifetime;
|
||||||
|
particle->accx = accelx;
|
||||||
|
particle->accy = accely;
|
||||||
|
particle->accz = accelz;
|
||||||
|
particle->bright = fullbright;
|
||||||
|
particle->size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_RunEffects
|
// P_RunEffects
|
||||||
//
|
//
|
||||||
|
|
|
@ -83,6 +83,7 @@ particle_t *JitterParticle (int ttl);
|
||||||
particle_t *JitterParticle (int ttl, double drift);
|
particle_t *JitterParticle (int ttl, double drift);
|
||||||
|
|
||||||
void P_ThinkParticles (void);
|
void P_ThinkParticles (void);
|
||||||
|
void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t velx, fixed_t vely, fixed_t velz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, BYTE size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz);
|
||||||
void P_InitEffects (void);
|
void P_InitEffects (void);
|
||||||
void P_RunEffects (void);
|
void P_RunEffects (void);
|
||||||
|
|
||||||
|
|
|
@ -5270,6 +5270,7 @@ int P_PushDown(AActor *thing, FChangePosition *cpos)
|
||||||
void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
|
void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
|
||||||
{
|
{
|
||||||
fixed_t oldfloorz = thing->floorz;
|
fixed_t oldfloorz = thing->floorz;
|
||||||
|
fixed_t oldz = thing->Z();
|
||||||
|
|
||||||
P_AdjustFloorCeil(thing, cpos);
|
P_AdjustFloorCeil(thing, cpos);
|
||||||
|
|
||||||
|
@ -5299,6 +5300,10 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
|
||||||
P_CheckFakeFloorTriggers(thing, oldz);
|
P_CheckFakeFloorTriggers(thing, oldz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (thing->player && thing->player->mo == thing)
|
||||||
|
{
|
||||||
|
thing->player->viewz += thing->Z() - oldz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -5350,6 +5355,10 @@ void PIT_FloorRaise(AActor *thing, FChangePosition *cpos)
|
||||||
thing->SetZ(oldz);
|
thing->SetZ(oldz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (thing->player && thing->player->mo == thing)
|
||||||
|
{
|
||||||
|
thing->player->viewz += thing->Z() - oldz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -5361,6 +5370,7 @@ void PIT_FloorRaise(AActor *thing, FChangePosition *cpos)
|
||||||
void PIT_CeilingLower(AActor *thing, FChangePosition *cpos)
|
void PIT_CeilingLower(AActor *thing, FChangePosition *cpos)
|
||||||
{
|
{
|
||||||
bool onfloor;
|
bool onfloor;
|
||||||
|
fixed_t oldz = thing->Z();
|
||||||
|
|
||||||
onfloor = thing->Z() <= thing->floorz;
|
onfloor = thing->Z() <= thing->floorz;
|
||||||
P_AdjustFloorCeil(thing, cpos);
|
P_AdjustFloorCeil(thing, cpos);
|
||||||
|
@ -5397,6 +5407,10 @@ void PIT_CeilingLower(AActor *thing, FChangePosition *cpos)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (thing->player && thing->player->mo == thing)
|
||||||
|
{
|
||||||
|
thing->player->viewz += thing->Z() - oldz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -5408,6 +5422,7 @@ void PIT_CeilingLower(AActor *thing, FChangePosition *cpos)
|
||||||
void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos)
|
void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos)
|
||||||
{
|
{
|
||||||
bool isgood = P_AdjustFloorCeil(thing, cpos);
|
bool isgood = P_AdjustFloorCeil(thing, cpos);
|
||||||
|
fixed_t oldz = thing->Z();
|
||||||
|
|
||||||
if (thing->flags4 & MF4_ACTLIKEBRIDGE) return; // do not move bridge things
|
if (thing->flags4 & MF4_ACTLIKEBRIDGE) return; // do not move bridge things
|
||||||
|
|
||||||
|
@ -5434,6 +5449,10 @@ void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos)
|
||||||
thing->SetZ( MIN(thing->ceilingz - thing->height, onmobj->Top()));
|
thing->SetZ( MIN(thing->ceilingz - thing->height, onmobj->Top()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (thing->player && thing->player->mo == thing)
|
||||||
|
{
|
||||||
|
thing->player->viewz += thing->Z() - oldz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -878,6 +878,7 @@ FArchive &operator<< (FArchive &arc, secspecial_t &p)
|
||||||
int special;
|
int special;
|
||||||
arc << special;
|
arc << special;
|
||||||
sector_t sec;
|
sector_t sec;
|
||||||
|
memset(&sec, 0, sizeof(sec));
|
||||||
P_InitSectorSpecial(&sec, special, true);
|
P_InitSectorSpecial(&sec, special, true);
|
||||||
sec.GetSpecial(&p);
|
sec.GetSpecial(&p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3350,6 +3350,7 @@ extern polyblock_t **PolyBlockMap;
|
||||||
|
|
||||||
void P_FreeLevelData ()
|
void P_FreeLevelData ()
|
||||||
{
|
{
|
||||||
|
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
|
||||||
Renderer->CleanLevelData();
|
Renderer->CleanLevelData();
|
||||||
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
|
||||||
SN_StopAllSequences ();
|
SN_StopAllSequences ();
|
||||||
|
@ -3581,7 +3582,6 @@ void P_SetupLevel (const char *lumpname, int position)
|
||||||
|
|
||||||
// Free all level data from the previous map
|
// Free all level data from the previous map
|
||||||
P_FreeLevelData ();
|
P_FreeLevelData ();
|
||||||
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
|
|
||||||
|
|
||||||
MapData *map = P_OpenMapData(lumpname, true);
|
MapData *map = P_OpenMapData(lumpname, true);
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
|
|
|
@ -157,7 +157,10 @@ public:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
IMPLEMENT_ABSTRACT_CLASS(DInterpolation)
|
IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation)
|
||||||
|
DECLARE_POINTER(Next)
|
||||||
|
DECLARE_POINTER(Prev)
|
||||||
|
END_POINTERS
|
||||||
IMPLEMENT_CLASS(DSectorPlaneInterpolation)
|
IMPLEMENT_CLASS(DSectorPlaneInterpolation)
|
||||||
IMPLEMENT_CLASS(DSectorScrollInterpolation)
|
IMPLEMENT_CLASS(DSectorScrollInterpolation)
|
||||||
IMPLEMENT_CLASS(DWallScrollInterpolation)
|
IMPLEMENT_CLASS(DWallScrollInterpolation)
|
||||||
|
@ -213,9 +216,9 @@ void FInterpolator::UpdateInterpolations()
|
||||||
void FInterpolator::AddInterpolation(DInterpolation *interp)
|
void FInterpolator::AddInterpolation(DInterpolation *interp)
|
||||||
{
|
{
|
||||||
interp->Next = Head;
|
interp->Next = Head;
|
||||||
if (Head != NULL) Head->Prev = &interp->Next;
|
if (Head != NULL) Head->Prev = interp;
|
||||||
|
interp->Prev = NULL;
|
||||||
Head = interp;
|
Head = interp;
|
||||||
interp->Prev = &Head;
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,15 +230,20 @@ void FInterpolator::AddInterpolation(DInterpolation *interp)
|
||||||
|
|
||||||
void FInterpolator::RemoveInterpolation(DInterpolation *interp)
|
void FInterpolator::RemoveInterpolation(DInterpolation *interp)
|
||||||
{
|
{
|
||||||
if (interp->Prev != NULL)
|
if (Head == interp)
|
||||||
{
|
{
|
||||||
*interp->Prev = interp->Next;
|
Head = interp->Next;
|
||||||
|
if (Head != NULL) Head->Prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (interp->Prev != NULL) interp->Prev->Next = interp->Next;
|
||||||
if (interp->Next != NULL) interp->Next->Prev = interp->Prev;
|
if (interp->Next != NULL) interp->Next->Prev = interp->Prev;
|
||||||
|
}
|
||||||
interp->Next = NULL;
|
interp->Next = NULL;
|
||||||
interp->Prev = NULL;
|
interp->Prev = NULL;
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -285,13 +293,15 @@ void FInterpolator::RestoreInterpolations()
|
||||||
|
|
||||||
void FInterpolator::ClearInterpolations()
|
void FInterpolator::ClearInterpolations()
|
||||||
{
|
{
|
||||||
for (DInterpolation *probe = Head; probe != NULL; )
|
DInterpolation *probe = Head;
|
||||||
|
Head = NULL;
|
||||||
|
while (probe != NULL)
|
||||||
{
|
{
|
||||||
DInterpolation *next = probe->Next;
|
DInterpolation *next = probe->Next;
|
||||||
|
probe->Next = probe->Prev = NULL;
|
||||||
probe->Destroy();
|
probe->Destroy();
|
||||||
probe = next;
|
probe = next;
|
||||||
}
|
}
|
||||||
Head = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -334,10 +344,6 @@ int DInterpolation::AddRef()
|
||||||
int DInterpolation::DelRef()
|
int DInterpolation::DelRef()
|
||||||
{
|
{
|
||||||
if (refcount > 0) --refcount;
|
if (refcount > 0) --refcount;
|
||||||
if (refcount <= 0 && !(ObjectFlags & OF_EuthanizeMe))
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
return refcount;
|
return refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,10 +492,17 @@ void DSectorPlaneInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
bakheight = *pheight;
|
bakheight = *pheight;
|
||||||
baktexz = sector->GetPlaneTexZ(pos);
|
baktexz = sector->GetPlaneTexZ(pos);
|
||||||
|
|
||||||
|
if (refcount == 0 && oldheight == bakheight)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
*pheight = oldheight + FixedMul(bakheight - oldheight, smoothratio);
|
*pheight = oldheight + FixedMul(bakheight - oldheight, smoothratio);
|
||||||
sector->SetPlaneTexZ(pos, oldtexz + FixedMul(baktexz - oldtexz, smoothratio));
|
sector->SetPlaneTexZ(pos, oldtexz + FixedMul(baktexz - oldtexz, smoothratio));
|
||||||
P_RecalculateAttached3DFloors(sector);
|
P_RecalculateAttached3DFloors(sector);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -612,9 +625,16 @@ void DSectorScrollInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
bakx = sector->GetXOffset(ceiling);
|
bakx = sector->GetXOffset(ceiling);
|
||||||
baky = sector->GetYOffset(ceiling, false);
|
baky = sector->GetYOffset(ceiling, false);
|
||||||
|
|
||||||
|
if (refcount == 0 && oldx == bakx && oldy == baky)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
sector->SetXOffset(ceiling, oldx + FixedMul(bakx - oldx, smoothratio));
|
sector->SetXOffset(ceiling, oldx + FixedMul(bakx - oldx, smoothratio));
|
||||||
sector->SetYOffset(ceiling, oldy + FixedMul(baky - oldy, smoothratio));
|
sector->SetYOffset(ceiling, oldy + FixedMul(baky - oldy, smoothratio));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -696,9 +716,16 @@ void DWallScrollInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
bakx = side->GetTextureXOffset(part);
|
bakx = side->GetTextureXOffset(part);
|
||||||
baky = side->GetTextureYOffset(part);
|
baky = side->GetTextureYOffset(part);
|
||||||
|
|
||||||
|
if (refcount == 0 && oldx == bakx && oldy == baky)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
side->SetTextureXOffset(part, oldx + FixedMul(bakx - oldx, smoothratio));
|
side->SetTextureXOffset(part, oldx + FixedMul(bakx - oldx, smoothratio));
|
||||||
side->SetTextureYOffset(part, oldy + FixedMul(baky - oldy, smoothratio));
|
side->SetTextureYOffset(part, oldy + FixedMul(baky - oldy, smoothratio));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -788,6 +815,7 @@ void DPolyobjInterpolation::Restore()
|
||||||
|
|
||||||
void DPolyobjInterpolation::Interpolate(fixed_t smoothratio)
|
void DPolyobjInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
{
|
{
|
||||||
|
bool changed = false;
|
||||||
for(unsigned int i = 0; i < poly->Vertices.Size(); i++)
|
for(unsigned int i = 0; i < poly->Vertices.Size(); i++)
|
||||||
{
|
{
|
||||||
fixed_t *px = &poly->Vertices[i]->x;
|
fixed_t *px = &poly->Vertices[i]->x;
|
||||||
|
@ -796,9 +824,19 @@ void DPolyobjInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
bakverts[i*2 ] = *px;
|
bakverts[i*2 ] = *px;
|
||||||
bakverts[i*2+1] = *py;
|
bakverts[i*2+1] = *py;
|
||||||
|
|
||||||
|
if (bakverts[i * 2] != oldverts[i * 2] || bakverts[i * 2 + 1] != oldverts[i * 2 + 1])
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
*px = oldverts[i * 2] + FixedMul(bakverts[i * 2] - oldverts[i * 2], smoothratio);
|
*px = oldverts[i * 2] + FixedMul(bakverts[i * 2] - oldverts[i * 2], smoothratio);
|
||||||
*py = oldverts[i * 2 + 1] + FixedMul(bakverts[i * 2 + 1] - oldverts[i * 2 + 1], smoothratio);
|
*py = oldverts[i * 2 + 1] + FixedMul(bakverts[i * 2 + 1] - oldverts[i * 2 + 1], smoothratio);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (refcount == 0 && !changed)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bakcx = poly->CenterSpot.x;
|
bakcx = poly->CenterSpot.x;
|
||||||
bakcy = poly->CenterSpot.y;
|
bakcy = poly->CenterSpot.y;
|
||||||
poly->CenterSpot.x = bakcx + FixedMul(bakcx - oldcx, smoothratio);
|
poly->CenterSpot.x = bakcx + FixedMul(bakcx - oldcx, smoothratio);
|
||||||
|
@ -806,6 +844,7 @@ void DPolyobjInterpolation::Interpolate(fixed_t smoothratio)
|
||||||
|
|
||||||
poly->ClearSubsectorLinks();
|
poly->ClearSubsectorLinks();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -13,12 +13,14 @@ class DInterpolation : public DObject
|
||||||
friend struct FInterpolator;
|
friend struct FInterpolator;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_CLASS(DInterpolation, DObject)
|
DECLARE_ABSTRACT_CLASS(DInterpolation, DObject)
|
||||||
|
HAS_OBJECT_POINTERS
|
||||||
|
|
||||||
DInterpolation *Next;
|
TObjPtr<DInterpolation> Next;
|
||||||
DInterpolation **Prev;
|
TObjPtr<DInterpolation> Prev;
|
||||||
int refcount;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int refcount;
|
||||||
|
|
||||||
DInterpolation();
|
DInterpolation();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -40,7 +42,7 @@ public:
|
||||||
|
|
||||||
struct FInterpolator
|
struct FInterpolator
|
||||||
{
|
{
|
||||||
DInterpolation *Head;
|
TObjPtr<DInterpolation> Head;
|
||||||
bool didInterp;
|
bool didInterp;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
|
|
@ -600,9 +600,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void Heapify();
|
void Heapify();
|
||||||
|
|
||||||
unsigned int Parent(unsigned int i) { return (i + 1u) / 2u - 1u; }
|
unsigned int Parent(unsigned int i) const { return (i + 1u) / 2u - 1u; }
|
||||||
unsigned int Left(unsigned int i) { return (i + 1u) * 2u - 1u; }
|
unsigned int Left(unsigned int i) const { return (i + 1u) * 2u - 1u; }
|
||||||
unsigned int Right(unsigned int i) { return (i + 1u) * 2u; }
|
unsigned int Right(unsigned int i) const { return (i + 1u) * 2u; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HMISong : public MIDIStreamer
|
class HMISong : public MIDIStreamer
|
||||||
|
@ -630,7 +630,7 @@ protected:
|
||||||
struct TrackInfo;
|
struct TrackInfo;
|
||||||
|
|
||||||
void ProcessInitialMetaEvents ();
|
void ProcessInitialMetaEvents ();
|
||||||
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay);
|
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
|
||||||
TrackInfo *FindNextDue ();
|
TrackInfo *FindNextDue ();
|
||||||
|
|
||||||
static DWORD ReadVarLenHMI(TrackInfo *);
|
static DWORD ReadVarLenHMI(TrackInfo *);
|
||||||
|
@ -673,7 +673,7 @@ protected:
|
||||||
void AdvanceSong(DWORD time);
|
void AdvanceSong(DWORD time);
|
||||||
|
|
||||||
void ProcessInitialMetaEvents();
|
void ProcessInitialMetaEvents();
|
||||||
DWORD *SendCommand (DWORD *event, EventSource track, DWORD delay);
|
DWORD *SendCommand (DWORD *event, EventSource track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
|
||||||
EventSource FindNextDue();
|
EventSource FindNextDue();
|
||||||
|
|
||||||
BYTE *MusHeader;
|
BYTE *MusHeader;
|
||||||
|
|
|
@ -523,7 +523,12 @@ DWORD *HMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
|
||||||
// Play all events for this tick.
|
// Play all events for this tick.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
DWORD *new_events = SendCommand(events, TrackDue, time);
|
bool sysex_noroom = false;
|
||||||
|
DWORD *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
|
||||||
|
if (sysex_noroom)
|
||||||
|
{
|
||||||
|
return events;
|
||||||
|
}
|
||||||
TrackDue = FindNextDue();
|
TrackDue = FindNextDue();
|
||||||
if (new_events != events)
|
if (new_events != events)
|
||||||
{
|
{
|
||||||
|
@ -568,7 +573,7 @@ void HMISong::AdvanceTracks(DWORD time)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
|
||||||
{
|
{
|
||||||
DWORD len;
|
DWORD len;
|
||||||
BYTE event, data1 = 0, data2 = 0;
|
BYTE event, data1 = 0, data2 = 0;
|
||||||
|
@ -584,10 +589,20 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
return events + 3;
|
return events + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysex_noroom = false;
|
||||||
|
size_t start_p = track->TrackP;
|
||||||
|
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
event = track->TrackBegin[track->TrackP++];
|
event = track->TrackBegin[track->TrackP++];
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
|
|
||||||
|
// The actual event type will be filled in below. If it's not a NOP,
|
||||||
|
// the events pointer will be advanced once the actual event is written.
|
||||||
|
// Otherwise, we do it at the end of the function.
|
||||||
|
events[0] = delay;
|
||||||
|
events[1] = 0;
|
||||||
|
events[2] = MEVT_NOP << 24;
|
||||||
|
|
||||||
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND && event != 0xFe)
|
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND && event != 0xFe)
|
||||||
{
|
{
|
||||||
// Normal short message
|
// Normal short message
|
||||||
|
@ -626,17 +641,10 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
data2 = VolumeControllerChange(event & 15, data2);
|
data2 = VolumeControllerChange(event & 15, data2);
|
||||||
}
|
}
|
||||||
|
|
||||||
events[0] = delay;
|
|
||||||
events[1] = 0;
|
|
||||||
if (event != MIDI_META)
|
if (event != MIDI_META)
|
||||||
{
|
{
|
||||||
events[2] = event | (data1<<8) | (data2<<16);
|
events[2] = event | (data1<<8) | (data2<<16);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
events[2] = MEVT_NOP << 24;
|
|
||||||
}
|
|
||||||
events += 3;
|
|
||||||
|
|
||||||
if (ReadVarLen == ReadVarLenHMI && (event & 0x70) == (MIDI_NOTEON & 0x70))
|
if (ReadVarLen == ReadVarLenHMI && (event & 0x70) == (MIDI_NOTEON & 0x70))
|
||||||
{ // HMI note on events include the time until an implied note off event.
|
{ // HMI note on events include the time until an implied note off event.
|
||||||
|
@ -645,14 +653,42 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Skip SysEx events just because I don't want to bother with them.
|
// SysEx events could potentially not have enough room in the buffer...
|
||||||
// The old MIDI player ignored them too, so this won't break
|
|
||||||
// anything that played before.
|
|
||||||
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
len = ReadVarLen(track);
|
len = ReadVarLen(track);
|
||||||
|
if (len >= (MAX_EVENTS-1)*3*4)
|
||||||
|
{ // This message will never fit. Throw it away.
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
}
|
}
|
||||||
|
else if (len + 12 >= (size_t)room * 4)
|
||||||
|
{ // Not enough room left in this buffer. Backup and wait for the next one.
|
||||||
|
track->TrackP = start_p;
|
||||||
|
sysex_noroom = true;
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BYTE *msg = (BYTE *)&events[3];
|
||||||
|
if (event == MIDI_SYSEX)
|
||||||
|
{ // Need to add the SysEx marker to the message.
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | (len + 1);
|
||||||
|
*msg++ = MIDI_SYSEX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | len;
|
||||||
|
}
|
||||||
|
memcpy(msg, &track->TrackBegin[track->TrackP], len);
|
||||||
|
msg += len;
|
||||||
|
// Must pad with 0
|
||||||
|
while ((size_t)msg & 3)
|
||||||
|
{
|
||||||
|
*msg++ = 0;
|
||||||
|
}
|
||||||
|
track->TrackP += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (event == MIDI_META)
|
else if (event == MIDI_META)
|
||||||
{
|
{
|
||||||
// It's a meta-event
|
// It's a meta-event
|
||||||
|
@ -677,7 +713,6 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
events[0] = delay;
|
events[0] = delay;
|
||||||
events[1] = 0;
|
events[1] = 0;
|
||||||
events[2] = (MEVT_TEMPO << 24) | Tempo;
|
events[2] = (MEVT_TEMPO << 24) | Tempo;
|
||||||
events += 3;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
|
@ -720,6 +755,18 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
{
|
{
|
||||||
track->Delay = ReadVarLen(track);
|
track->Delay = ReadVarLen(track);
|
||||||
}
|
}
|
||||||
|
// Advance events pointer unless this is a non-delaying NOP.
|
||||||
|
if (events[0] != 0 || MEVT_EVENTTYPE(events[2]) != MEVT_NOP)
|
||||||
|
{
|
||||||
|
if (MEVT_EVENTTYPE(events[2]) == MEVT_LONGMSG)
|
||||||
|
{
|
||||||
|
events += 3 + ((MEVT_EVENTPARM(events[2]) + 3) >> 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -384,6 +384,11 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
event = track->TrackBegin[track->TrackP++];
|
event = track->TrackBegin[track->TrackP++];
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
|
|
||||||
|
// The actual event type will be filled in below.
|
||||||
|
events[0] = delay;
|
||||||
|
events[1] = 0;
|
||||||
|
events[2] = MEVT_NOP << 24;
|
||||||
|
|
||||||
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND)
|
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
// Normal short message
|
// Normal short message
|
||||||
|
@ -582,17 +587,10 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events[0] = delay;
|
|
||||||
events[1] = 0;
|
|
||||||
if (event != MIDI_META && (!track->Designated || (track->Designation & DesignationMask)))
|
if (event != MIDI_META && (!track->Designated || (track->Designation & DesignationMask)))
|
||||||
{
|
{
|
||||||
events[2] = event | (data1<<8) | (data2<<16);
|
events[2] = event | (data1<<8) | (data2<<16);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
events[2] = MEVT_NOP << 24;
|
|
||||||
}
|
|
||||||
events += 3;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -612,8 +610,6 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
events[0] = delay;
|
|
||||||
events[1] = 0;
|
|
||||||
BYTE *msg = (BYTE *)&events[3];
|
BYTE *msg = (BYTE *)&events[3];
|
||||||
if (event == MIDI_SYSEX)
|
if (event == MIDI_SYSEX)
|
||||||
{ // Need to add the SysEx marker to the message.
|
{ // Need to add the SysEx marker to the message.
|
||||||
|
@ -631,7 +627,6 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
{
|
{
|
||||||
*msg++ = 0;
|
*msg++ = 0;
|
||||||
}
|
}
|
||||||
events = (DWORD *)msg;
|
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,7 +654,6 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
events[0] = delay;
|
events[0] = delay;
|
||||||
events[1] = 0;
|
events[1] = 0;
|
||||||
events[2] = (MEVT_TEMPO << 24) | Tempo;
|
events[2] = (MEVT_TEMPO << 24) | Tempo;
|
||||||
events += 3;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
|
@ -678,6 +672,18 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptr
|
||||||
{
|
{
|
||||||
track->Delay = track->ReadVarLen();
|
track->Delay = track->ReadVarLen();
|
||||||
}
|
}
|
||||||
|
// Advance events pointer unless this is a non-delaying NOP.
|
||||||
|
if (events[0] != 0 || MEVT_EVENTTYPE(events[2]) != MEVT_NOP)
|
||||||
|
{
|
||||||
|
if (MEVT_EVENTTYPE(events[2]) == MEVT_LONGMSG)
|
||||||
|
{
|
||||||
|
events += 3 + ((MEVT_EVENTPARM(events[2]) + 3) >> 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,12 @@ DWORD *XMISong::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
|
||||||
// Play all events for this tick.
|
// Play all events for this tick.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
DWORD *new_events = SendCommand(events, EventDue, time);
|
bool sysex_noroom = false;
|
||||||
|
DWORD *new_events = SendCommand(events, EventDue, time, max_event_p - events, sysex_noroom);
|
||||||
|
if (sysex_noroom)
|
||||||
|
{
|
||||||
|
return events;
|
||||||
|
}
|
||||||
EventDue = FindNextDue();
|
EventDue = FindNextDue();
|
||||||
if (new_events != events)
|
if (new_events != events)
|
||||||
{
|
{
|
||||||
|
@ -382,7 +387,7 @@ void XMISong::AdvanceSong(DWORD time)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay)
|
DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
|
||||||
{
|
{
|
||||||
DWORD len;
|
DWORD len;
|
||||||
BYTE event, data1 = 0, data2 = 0;
|
BYTE event, data1 = 0, data2 = 0;
|
||||||
|
@ -399,10 +404,20 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay)
|
||||||
|
|
||||||
TrackInfo *track = CurrSong;
|
TrackInfo *track = CurrSong;
|
||||||
|
|
||||||
|
sysex_noroom = false;
|
||||||
|
size_t start_p = track->EventP;
|
||||||
|
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
event = track->EventChunk[track->EventP++];
|
event = track->EventChunk[track->EventP++];
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
|
|
||||||
|
// The actual event type will be filled in below. If it's not a NOP,
|
||||||
|
// the events pointer will be advanced once the actual event is written.
|
||||||
|
// Otherwise, we do it at the end of the function.
|
||||||
|
events[0] = delay;
|
||||||
|
events[1] = 0;
|
||||||
|
events[2] = MEVT_NOP << 24;
|
||||||
|
|
||||||
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND)
|
if (event != MIDI_SYSEX && event != MIDI_META && event != MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
// Normal short message
|
// Normal short message
|
||||||
|
@ -499,10 +514,6 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay)
|
||||||
{
|
{
|
||||||
events[2] = event | (data1<<8) | (data2<<16);
|
events[2] = event | (data1<<8) | (data2<<16);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
events[2] = MEVT_NOP << 24;
|
|
||||||
}
|
|
||||||
events += 3;
|
events += 3;
|
||||||
|
|
||||||
|
|
||||||
|
@ -513,14 +524,42 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Skip SysEx events just because I don't want to bother with them.
|
// SysEx events could potentially not have enough room in the buffer...
|
||||||
// The old MIDI player ignored them too, so this won't break
|
|
||||||
// anything that played before.
|
|
||||||
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
len = track->ReadVarLen();
|
len = track->ReadVarLen();
|
||||||
|
if (len >= (MAX_EVENTS-1)*3*4)
|
||||||
|
{ // This message will never fit. Throw it away.
|
||||||
track->EventP += len;
|
track->EventP += len;
|
||||||
}
|
}
|
||||||
|
else if (len + 12 >= (size_t)room * 4)
|
||||||
|
{ // Not enough room left in this buffer. Backup and wait for the next one.
|
||||||
|
track->EventP = start_p;
|
||||||
|
sysex_noroom = true;
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BYTE *msg = (BYTE *)&events[3];
|
||||||
|
if (event == MIDI_SYSEX)
|
||||||
|
{ // Need to add the SysEx marker to the message.
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | (len + 1);
|
||||||
|
*msg++ = MIDI_SYSEX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | len;
|
||||||
|
}
|
||||||
|
memcpy(msg, &track->EventChunk[track->EventP++], len);
|
||||||
|
msg += len;
|
||||||
|
// Must pad with 0
|
||||||
|
while ((size_t)msg & 3)
|
||||||
|
{
|
||||||
|
*msg++ = 0;
|
||||||
|
}
|
||||||
|
track->EventP += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (event == MIDI_META)
|
else if (event == MIDI_META)
|
||||||
{
|
{
|
||||||
// It's a meta-event
|
// It's a meta-event
|
||||||
|
@ -551,6 +590,18 @@ DWORD *XMISong::SendCommand (DWORD *events, EventSource due, DWORD delay)
|
||||||
{
|
{
|
||||||
track->Delay = track->ReadDelay();
|
track->Delay = track->ReadDelay();
|
||||||
}
|
}
|
||||||
|
// Advance events pointer unless this is a non-delaying NOP.
|
||||||
|
if (events[0] != 0 || MEVT_EVENTTYPE(events[2]) != MEVT_NOP)
|
||||||
|
{
|
||||||
|
if (MEVT_EVENTTYPE(events[2]) == MEVT_LONGMSG)
|
||||||
|
{
|
||||||
|
events += 3 + ((MEVT_EVENTPARM(events[2]) + 3) >> 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
|
#include "p_effect.h"
|
||||||
#include "p_enemy.h"
|
#include "p_enemy.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "decallib.h"
|
#include "decallib.h"
|
||||||
|
@ -2876,6 +2877,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// A_SpawnParticle
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle)
|
||||||
|
{
|
||||||
|
PARAM_ACTION_PROLOGUE;
|
||||||
|
PARAM_FIXED (xoff);
|
||||||
|
PARAM_FIXED (yoff);
|
||||||
|
PARAM_FIXED (zoff);
|
||||||
|
PARAM_FIXED (xvel);
|
||||||
|
PARAM_FIXED (yvel);
|
||||||
|
PARAM_FIXED (zvel);
|
||||||
|
PARAM_COLOR (color);
|
||||||
|
PARAM_INT (lifetime);
|
||||||
|
PARAM_BOOL_OPT (fullbright) { fullbright = false; }
|
||||||
|
PARAM_INT_OPT (startalpha) { startalpha = 255; } // Byte trans
|
||||||
|
PARAM_INT_OPT (size) { size = -1; }
|
||||||
|
PARAM_INT_OPT (fadestep) { fadestep = -1; }
|
||||||
|
PARAM_FIXED_OPT (accelx) { accelx = 0; }
|
||||||
|
PARAM_FIXED_OPT (accely) { accely = 0; }
|
||||||
|
PARAM_FIXED_OPT (accelz) { accelz = 0; }
|
||||||
|
|
||||||
|
startalpha = clamp<int>(startalpha, 0, 0xFF); // Clamp to byte
|
||||||
|
lifetime = clamp<int>(lifetime, 0, 0xFF); // Clamp to byte
|
||||||
|
fadestep = clamp<int>(fadestep, -1, 0xFF); // Clamp to byte inc. -1 (indicating automatic)
|
||||||
|
size = clamp<int>(size, 0, 0xFF); // Clamp to byte
|
||||||
|
|
||||||
|
if (lifetime != 0)
|
||||||
|
{
|
||||||
|
fixedvec3 pos = self->Vec3Offset(xoff, yoff, zoff);
|
||||||
|
P_SpawnParticle(pos.x, pos.y, pos.z, xvel, yvel, zvel, color, fullbright, startalpha, lifetime, size, fadestep, accelx, accely, accelz);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -4580,6 +4617,7 @@ enum T_Flags
|
||||||
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
|
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
|
||||||
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
|
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
|
||||||
TF_OVERRIDE = 0x00000400, // Ignore NOTELEPORT.
|
TF_OVERRIDE = 0x00000400, // Ignore NOTELEPORT.
|
||||||
|
TF_SENSITIVEZ = 0x00000800, // Fail if the actor wouldn't fit in the position (for Z).
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
|
||||||
|
@ -4644,6 +4682,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
|
||||||
return numret;
|
return numret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [MC] By default, the function adjusts the actor's Z if it's below the floor or above the ceiling.
|
||||||
|
// This can be an issue as actors designed to maintain specific z positions wind up teleporting
|
||||||
|
// anyway when they should not, such as a floor rising above or ceiling lowering below the position
|
||||||
|
// of the spot.
|
||||||
|
if (flags & TF_SENSITIVEZ)
|
||||||
|
{
|
||||||
|
fixed_t posz = (flags & TF_USESPOTZ) ? spot->Z() : spot->floorz;
|
||||||
|
if ((posz + ref->height > spot->ceilingz) || (posz < spot->floorz))
|
||||||
|
{
|
||||||
|
return numret;
|
||||||
|
}
|
||||||
|
}
|
||||||
fixedvec3 prev = ref->Pos();
|
fixedvec3 prev = ref->Pos();
|
||||||
fixed_t aboveFloor = spot->Z() - spot->floorz;
|
fixed_t aboveFloor = spot->Z() - spot->floorz;
|
||||||
fixed_t finalz = spot->floorz + aboveFloor;
|
fixed_t finalz = spot->floorz + aboveFloor;
|
||||||
|
@ -4654,7 +4704,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
|
||||||
finalz = spot->floorz;
|
finalz = spot->floorz;
|
||||||
|
|
||||||
//Take precedence and cooperate with telefragging first.
|
//Take precedence and cooperate with telefragging first.
|
||||||
bool tele_result = P_TeleportMove(ref, spot->X(), spot->Y(), finalz, flags & TF_TELEFRAG);
|
bool tele_result = P_TeleportMove(ref, spot->X(), spot->Y(), finalz, !!(flags & TF_TELEFRAG));
|
||||||
|
|
||||||
if (!tele_result && (flags & TF_FORCED))
|
if (!tele_result && (flags & TF_FORCED))
|
||||||
{
|
{
|
||||||
|
@ -4695,7 +4745,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
|
||||||
}
|
}
|
||||||
|
|
||||||
ref->SetZ((flags & TF_USESPOTZ) ? spot->Z() : ref->floorz, false);
|
ref->SetZ((flags & TF_USESPOTZ) ? spot->Z() : ref->floorz, false);
|
||||||
self->SetZ((flags & TF_USESPOTZ) ? spot->Z() : self->floorz, false);
|
|
||||||
|
|
||||||
if (!(flags & TF_KEEPANGLE))
|
if (!(flags & TF_KEEPANGLE))
|
||||||
ref->angle = spot->angle;
|
ref->angle = spot->angle;
|
||||||
|
|
|
@ -202,6 +202,7 @@ ACTOR Actor native //: Thinker
|
||||||
action native A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT);
|
action native A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT);
|
||||||
action native A_SetMass(int mass);
|
action native A_SetMass(int mass);
|
||||||
action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1);
|
action native A_SpawnDebris(class<Actor> spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1);
|
||||||
|
action native A_SpawnParticle(float xoff, float yoff, float zoff, float velx, float vely, float velz, color color1, int lifetime, bool fullbright = false, int startalpha = 255, int size = 1, int fadestep = -1, float accelx = 0.0, float accely = 0.0, float accelz = 0.0);
|
||||||
action native A_CheckSight(state label);
|
action native A_CheckSight(state label);
|
||||||
action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
action native A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
||||||
action native A_DropInventory(class<Inventory> itemtype);
|
action native A_DropInventory(class<Inventory> itemtype);
|
||||||
|
|
|
@ -208,6 +208,7 @@ enum
|
||||||
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
|
TF_USEACTORFOG = 0x00000100, // Use the actor's TeleFogSourceType and TeleFogDestType fogs.
|
||||||
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
|
TF_NOJUMP = 0x00000200, // Don't jump after teleporting.
|
||||||
TF_OVERRIDE = 0x00000400, // Ignore NOTELEPORT.
|
TF_OVERRIDE = 0x00000400, // Ignore NOTELEPORT.
|
||||||
|
TF_SENSITIVEZ = 0x00000800, // Fail if the actor wouldn't fit in the position (for Z).
|
||||||
|
|
||||||
TF_KEEPORIENTATION = TF_KEEPVELOCITY|TF_KEEPANGLE,
|
TF_KEEPORIENTATION = TF_KEEPVELOCITY|TF_KEEPANGLE,
|
||||||
TF_NOFOG = TF_NOSRCFOG|TF_NODESTFOG,
|
TF_NOFOG = TF_NOSRCFOG|TF_NODESTFOG,
|
||||||
|
|
Loading…
Reference in New Issue