diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 235a479336..fd41d6e51d 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2306,6 +2306,12 @@ void FBehavior::LoadScriptsDirectory () default: break; } + +// [EP] Clang 3.5.0 optimizer miscompiles this function and causes random +// crashes in the program. I hope that Clang 3.5.x will fix this. +#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ >= 5 + asm("" : "+g" (NumScripts)); +#endif for (i = 0; i < NumScripts; ++i) { Scripts[i].Flags = 0; @@ -4361,6 +4367,8 @@ enum EACSFunctions ACSF_ChangeActorAngle, ACSF_ChangeActorPitch, // 80 ACSF_GetArmorInfo, + ACSF_DropInventory, + ACSF_PickActor, /* Zandronum's - these must be skipped when we reach 99! -100:ResetMap(0), @@ -5485,6 +5493,42 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } + case ACSF_DropInventory: + { + const char *type = FBehavior::StaticLookupString(args[1]); + AInventory *inv; + + if (type != NULL) + { + if (args[0] == 0) + { + if (activator != NULL) + { + inv = activator->FindInventory(type); + if (inv) + { + activator->DropInventory(inv); + } + } + } + else + { + FActorIterator it(args[0]); + AActor *actor; + + while ((actor = it.Next()) != NULL) + { + inv = actor->FindInventory(type); + if (inv) + { + actor->DropInventory(inv); + } + } + } + } + break; + } + case ACSF_CheckFlag: { AActor *actor = SingleActorFromTID(args[0], activator); @@ -5550,6 +5594,38 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } break; + case ACSF_PickActor: + if (argCount >= 5) + { + actor = SingleActorFromTID(args[0], activator); + if (actor == NULL) + { + return 0; + } + + DWORD actorMask = MF_SHOOTABLE; + if (argCount >= 6) { + actorMask = args[5]; + } + + DWORD wallMask = ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN; + if (argCount >= 7) { + wallMask = args[6]; + } + + AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask); + if (pickedActor == NULL) { + return 0; + } + + pickedActor->RemoveFromHash(); + pickedActor->tid = args[4]; + pickedActor->AddToHash(); + + return 1; + } + break; + default: break; } diff --git a/src/p_local.h b/src/p_local.h index 58d9d02e50..939018734a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -462,6 +462,7 @@ enum // P_LineAttack flags AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); +AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, DWORD actorMask, DWORD wallMask); void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version diff --git a/src/p_map.cpp b/src/p_map.cpp index 4ea8762ec8..2274e75719 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3783,6 +3783,52 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance, return NULL; } +//========================================================================== +// +// P_LinePickActor +// +//========================================================================== + +AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch, + DWORD actorMask, DWORD wallMask) +{ + fixed_t vx, vy, vz, shootz; + + angle >>= ANGLETOFINESHIFT; + pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT; + + vx = FixedMul(finecosine[pitch], finecosine[angle]); + vy = FixedMul(finecosine[pitch], finesine[angle]); + vz = -finesine[pitch]; + + shootz = t1->z - t1->floorclip + (t1->height >> 1); + if (t1->player != NULL) + { + shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor); + } + else + { + shootz += 8 * FRACUNIT; + } + + FTraceResults trace; + Origin TData; + + TData.Caller = t1; + TData.hitGhosts = true; + + if (Trace(t1->x, t1->y, shootz, t1->Sector, vx, vy, vz, distance, + actorMask, wallMask, t1, trace, TRACE_NoSky, CheckForActor, &TData)) + { + if (trace.HitType == TRACE_HitActor) + { + return trace.Actor; + } + } + + return NULL; +} + //========================================================================== // // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 50461c43a9..d035e0117b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -206,7 +206,7 @@ void AActor::Serialize (FArchive &arc) { arc << flags7; } - if (SaveVersion >= 4511) + if (SaveVersion >= 4512) { arc << weaponspecial; } diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 9070012bae..7a5d0bda8e 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2347,14 +2347,14 @@ class AMusicChanger : public ASectorAction { DECLARE_CLASS (AMusicChanger, ASectorAction) public: - virtual bool TriggerAction (AActor *triggerer, int activationType); + virtual bool DoTriggerAction (AActor *triggerer, int activationType); virtual void Tick(); virtual void PostBeginPlay(); }; IMPLEMENT_CLASS(AMusicChanger) -bool AMusicChanger::TriggerAction (AActor *triggerer, int activationType) +bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType) { if (activationType & SECSPAC_Enter) { @@ -2364,7 +2364,7 @@ bool AMusicChanger::TriggerAction (AActor *triggerer, int activationType) reactiontime = 30; } } - return Super::TriggerAction (triggerer, activationType); + return Super::DoTriggerAction (triggerer, activationType); } void AMusicChanger::Tick() diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 531766a7a5..b417d8b170 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1318,23 +1318,23 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx) SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]); // If the sound is voc, use the custom loader. - // If the sound is raw, just load it as such. - // Otherwise, try the sound as DMX format. - // If that fails, let the sound system try and figure it out. if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0) { sfx->data = GSnd->LoadSoundVoc(sfxdata, size); } + // If the sound is raw, just load it as such. else if (sfx->bLoadRAW) { sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart); } + // Otherwise, try the sound as DMX format. else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8) { int frequency = LittleShort(((WORD *)sfxdata)[1]); if (frequency == 0) frequency = 11025; sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart); } + // If that fails, let the sound system try and figure it out. else { sfx->data = GSnd->LoadSound(sfxdata, size); diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 9b3027a7d8..8fea36c375 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -123,14 +123,13 @@ void I_EndRead(void) static DWORD TicStart; -static DWORD TicNext; static DWORD BaseTime; static int TicFrozen; // Signal based timer. static Semaphore timerWait; static int tics; -static DWORD sig_start, sig_next; +static DWORD sig_start; void I_SelectTimer(); @@ -169,7 +168,6 @@ int I_GetTimePolled (bool saveMS) if (saveMS) { TicStart = tm; - TicNext = Scale((Scale (tm, TICRATE, 1000) + 1), 1000, TICRATE); } return Scale(tm - BaseTime, TICRATE, 1000); } @@ -179,7 +177,6 @@ int I_GetTimeSignaled (bool saveMS) if (saveMS) { TicStart = sig_start; - TicNext = sig_next; } return tics; } @@ -250,7 +247,6 @@ void I_HandleAlarm (int sig) if(!TicFrozen) tics++; sig_start = SDL_GetTicks(); - sig_next = Scale((Scale (sig_start, TICRATE, 1000) + 1), 1000, TICRATE); SEMAPHORE_SIGNAL(timerWait) } @@ -293,15 +289,14 @@ void I_SelectTimer() fixed_t I_GetTimeFrac (uint32 *ms) { DWORD now = SDL_GetTicks (); - if (ms) *ms = TicNext; - DWORD step = TicNext - TicStart; - if (step == 0) + if (ms) *ms = TicStart + (1000 / TICRATE); + if (TicStart == 0) { return FRACUNIT; } else { - fixed_t frac = clamp ((now - TicStart)*FRACUNIT/step, 0, FRACUNIT); + fixed_t frac = clamp ((now - TicStart)*FRACUNIT*TICRATE/1000, 0, FRACUNIT); return frac; } } diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 852d50a6b7..efac427b53 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -553,6 +553,7 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length) break; default: break; } + i += blocksize; } } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index b1c9e90658..f80e89aad2 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1755,6 +1755,8 @@ enum SIX_Flags SIXF_TRANSFERSPECIAL = 1 << 15, SIXF_CLEARCALLERSPECIAL = 1 << 16, SIXF_TRANSFERSTENCILCOL = 1 << 17, + SIXF_TRANSFERALPHA = 1 << 18, + SIXF_TRANSFERRENDERSTYLE = 1 << 19, }; static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) @@ -1843,6 +1845,10 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) // If this is a missile or something else set the target to the originator mo->target = originator ? originator : self; } + if (flags & SIXF_SETMASTER) + { + mo->master = originator; + } if (flags & SIXF_TRANSFERSCALE) { mo->scaleX = self->scaleX; @@ -1871,6 +1877,14 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) { mo->fillcolor = self->fillcolor; } + if (flags & SIXF_TRANSFERALPHA) + { + mo->alpha = self->alpha; + } + if (flags & SIXF_TRANSFERRENDERSTYLE) + { + mo->RenderStyle = self->RenderStyle; + } return true; } @@ -4966,3 +4980,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem) P_DropItem(self, spawntype, amount, chance); } + +//========================================================================== +// +// A_SetSpeed +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed) +{ + ACTION_PARAM_START(1); + ACTION_PARAM_FIXED(speed, 0); + + self->Speed = speed; +} diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index c578ddb2bf..7dbf5ec36d 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -88,6 +88,7 @@ DEFINE_MEMBER_VARIABLE(height, AActor) DEFINE_MEMBER_VARIABLE(radius, AActor) DEFINE_MEMBER_VARIABLE(reactiontime, AActor) DEFINE_MEMBER_VARIABLE(meleerange, AActor) +DEFINE_MEMBER_VARIABLE(Speed, AActor) //========================================================================== diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 498003b4ee..88e6084b64 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -374,6 +374,8 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) FScriptPosition::ErrorCounter++; } + + FName symname = sc.String; if (sc.CheckToken('[')) { @@ -391,6 +393,15 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) } sc.MustGetToken(';'); + // We must ensure that we do not define duplicates, even when they come from a parent table. + if (symt->FindSymbol(symname, true) != NULL) + { + sc.ScriptMessage ("'%s' is already defined in '%s' or one of its ancestors.", + symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); + FScriptPosition::ErrorCounter++; + return; + } + PSymbolVariable *sym = new PSymbolVariable(symname); sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1)); sym->ValueType = valuetype; diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 501933f04a..e66226c1ed 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -62,6 +62,7 @@ ACTOR Actor native //: Thinker native fixed_t radius; native int reactiontime; native fixed_t meleerange; + native fixed_t speed; // Meh, MBF redundant functions. Only for DeHackEd support. action native A_Turn(float angle = 0); @@ -302,6 +303,7 @@ ACTOR Actor native //: Thinker action native A_SetTics(int tics); action native A_SetDamageType(name damagetype); action native A_DropItem(class item, int dropamount = -1, int chance = 256); + action native A_SetSpeed(float speed); action native A_CheckSightOrRange(float distance, state label); action native A_CheckRange(float distance, state label); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index d5358e5af4..bf998e6b07 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -65,6 +65,8 @@ const int SXF_TRANSFERSCALE = 16384; const int SXF_TRANSFERSPECIAL = 32768; const int SXF_CLEARCALLERSPECIAL = 65536; const int SXF_TRANSFERSTENCILCOL = 131072; +const int SXF_TRANSFERALPHA = 262144; +const int SXF_TRANSFERRENDERSTYLE = 524288; // Flags for A_Chase const int CHF_FASTCHASE = 1;