Remove ZPolyobject due to licensing concerns.

This commit is contained in:
Mari the Deer 2022-10-07 00:55:20 +02:00
commit f134375f7e
14 changed files with 20 additions and 559 deletions

View file

@ -18,7 +18,6 @@ Most of the work here is original, but there are some notable exceptions:
- In addition, a whole lot of stock sounds and internet meme sounds have also been used.
- Some sprites and sounds are taken from (shareware) Wolfenstein 3D.
- This mod uses Gutamatics, by Gutawer. Big thanks.
- This mod uses Mikolah's ZPolyobject library. Many thanks too.
- Title theme, "Traumatic State", by Teque (which a lot of people just know as "the AS-Golgotha music").
- Intermission theme, "Dragony", also by Teque (very comfy music considering the rest of his repertoire).
- Startup/credits theme, "Hidden Tune #242", also by Teque too (super comfy music, ideal for this use).

View file

@ -355,7 +355,6 @@ SWWM_CMAB2 = "For being an amazing friend who believes in me, and for inspiring
SWWM_CDRAGON2 = "For being a good pet dragon who cares about me.";
SWWM_CLUCY2 = "For the Tewi font, which I've used for many many years. I hope you're doing well, wherever you are.";
SWWM_CGUTA2 = "For the Gutamatics library, and for helping me with learning ZScript.";
SWWM_CMIKO2 = "For the VERY useful ZPolyobject library.";
SWWM_CKEKS2 = "For assistance with exception handling code, and also for being such a cool Touhou nerd.";
SWWM_CZN2 = "For slope alignment code, and to Nash also for being a cool smart cactus dude.";
SWWM_CVAL2 = "For the custom Nashgore footprints, and for being a good friend and cute bun.";

View file

@ -314,7 +314,6 @@ SWWM_CMAB2 = "Por ser una grandísima amiga que cree en mí, y por inspirarme a
SWWM_CDRAGON2 = "Por ser un buen dragón mascota que se preocupa por mí.";
SWWM_CLUCY2 = "Por la fuente Tewi, que he seguido usando todos estos años. Espero que estés donde estés, te encuentres bien.";
SWWM_CGUTA2 = "Por la librería de Gutamatics, y por ayudarme a aprender ZScript.";
SWWM_CMIKO2 = "Por la MUY útil librería de ZPolyobject.";
SWWM_CKEKS2 = "Por asistencia con el código de manejo de excepciones, y también por ser un friki tan guay de Touhou.";
SWWM_CZN2 = "Por el código para alineación con superficies inclinadas, y a Nash además por ser un molón tío cactus listo.";
SWWM_CVAL2 = "Por las huellas personalizadas para Nashgore, y por ser una buena amiga y conejita mona.";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r543 \cu(Wed 5 Oct 17:10:23 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r543 \cu(2022-10-05 17:10:23)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r544 \cu(Fri 7 Oct 00:55:20 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r544 \cu(2022-10-07 00:55:20)\c-";

View file

@ -9,8 +9,6 @@ version "4.9"
// Gutamatics
#include "zscript/swwm_Gutamatics/Include.zsc"
// ZPolyobject
#include "zscript/swwm_Polyobjects/Polyobjects.zs"
// utility code
#include "zscript/utility/swwm_coordutil.zsc"
#include "zscript/utility/swwm_utility.zsc"

View file

@ -197,7 +197,6 @@ Class SWWMCreditsMenu : GenericMenu
cthanks.Push(new("SWWMCreditsEntry").Init("KynikossDragonn","$SWWM_CDRAGON2"));
cthanks.Push(new("SWWMCreditsEntry").Init("Lucy","$SWWM_CLUCY2"));
cthanks.Push(new("SWWMCreditsEntry").Init("Gutawer","$SWWM_CGUTA2"));
cthanks.Push(new("SWWMCreditsEntry").Init("Mikolah","$SWWM_CMIKO2"));
cthanks.Push(new("SWWMCreditsEntry").Init("KeksDose","$SWWM_CKEKS2"));
cthanks.Push(new("SWWMCreditsEntry").Init("ZZYZX & Nash","$SWWM_CZN2"));
cthanks.Push(new("SWWMCreditsEntry").Init("Val Pal","$SWWM_CVAL2"));

View file

@ -1,48 +0,0 @@
class swwm_PolyobjectEffector: Thinker abstract
{
// Base abstract class for Polyobject Effectors
// Polyobject Effectors affect how a polyobject behaves.
// Polyobject Effectors contain a pointer to the next Effector of a polyobject,
// forming a circular linked list.
// To add an effector to a polyobject, call AddEffector() on a PolyobjectHandle.
// To remove an effector, simply call Destroy() on it.
swwm_PolyobjectHandle Polyobject;
swwm_PolyobjectEffector Next;
// OnAdd() is called once after adding the effector to a PolyobjectHandle
virtual void OnAdd()
{
}
// PolyTick() is called every tic by a PolyobjectHandle
virtual void PolyTick()
{
}
override void OnDestroy()
{
swwm_PolyobjectEffector e = Polyobject.EffectorList;
if (e != NULL)
{
// Find previous effector
while (e && e.Next != self)
{
e = e.Next;
}
// Link previous effector to the next effector
e.Next = Next;
// Check if this effector is the last one
if (e == self)
{
// Polyobject has no other effectors, set EffectorList to NULL
Polyobject.EffectorList = NULL;
}
}
Super.OnDestroy();
}
}

View file

@ -1,359 +0,0 @@
class swwm_PolyobjectHandle: Thinker
{
// This thinker keeps track of a polyobject's position, angle, movement speed etc.
// Instances of this thinker should only be created by the included map postprocessor
enum EPolyobjType
{
POTYP_NORMAL = 9301, // Normal StartSpot
POTYP_CRUSH = 9302, // Crush StartSpot
POTYP_HURT = 9303 // Hurt StartSpot
}
// Polyobject Number
int PolyobjectNum;
// Line defining the polyobject (Polyobj_StartLine, or one of Polyobj_ExplicitLine)
Line StartLine;
// [MK] All lines belonging to the polyobject
Array<Line> Lines;
// Initial angle of StartLine
double StartAngle;
// Last tic angle of StartLine
double LastAngle;
// Starting positions of StartLine vertices
Vector2[2] VertexStartingPos;
// Last tic positions of StartLine vertices
Vector2[2] VertexLastPos;
// Last tic position of the polyobject
Vector2 LastPos;
// SoundSequence number
int SoundSequenceNum;
// StartSpot position
Vector2 StartSpotPos;
// For bounds checking
double z;
// Sector the polyobject spawns in ()
Sector StartSector;
// Polyobject type (normal, crush, hurt)
EPolyobjType Type;
// Mirror Polyobject
swwm_PolyobjectHandle Mirror;
// Circular linked list of attached Polyobject Effectors
swwm_PolyobjectEffector EffectorList;
// Whether the initalization has finished
bool IsInitialized;
// Creates a PolyobjectHandle
static swwm_PolyobjectHandle Create()
{
swwm_PolyobjectHandle po = swwm_PolyobjectHandle(new('swwm_PolyobjectHandle'));
// Sets the underlying Thinker StatNum to 127 so that LastPos, LastAngle etc. get
// updated after all the other thinkers.
po.ChangeStatNum(127);
return po;
}
// Returns a PolyobjectHandle corresponding to the provided polyobject number
// Returns NULL if no such handler exists.
static swwm_PolyobjectHandle FindPolyobj(int pobjnum)
{
swwm_PolyobjectHandle po;
let it = ThinkerIterator.Create('swwm_PolyobjectHandle');
while ((po = swwm_PolyobjectHandle(it.Next())) != NULL)
{
if (po.PolyobjectNum == pobjnum)
return po;
}
return NULL;
}
// Adds effector to the end of current effector list
void AddEffector(swwm_PolyobjectEffector effector)
{
effector.Polyobject = self;
// If effector list is empty, new effector becomes head of the list
if (EffectorList == NULL)
{
EffectorList = effector;
effector.Next = effector;
}
else
{
swwm_PolyobjectEffector e = EffectorList;
// Go through every effector until the last item
while (e.Next != EffectorList)
{
e = e.Next;
}
effector.Next = EffectorList;
e.Next = effector;
}
if (IsInitialized)
{
// If we're initialized, run the OnAdd effect immediately
effector.OnAdd();
}
}
// Finds effector of specified class, and returns it
swwm_PolyobjectEffector FindEffector(class<swwm_PolyobjectEffector> effectorclass)
{
// No effectors? Nothing to find then
if (EffectorList == NULL)
return NULL;
// Go through each effector
swwm_PolyobjectEffector e = EffectorList;
do
{
// Effector is of specified class, return it
if (e is effectorclass)
return e;
e = e.Next;
}
while (e != EffectorList);
return NULL;
}
override void PostBeginPlay()
{
// Initialization shouldn't happen when reentering the map
if (Level.Time > 0)
return;
// Map has no lines corresponding to this polyobject, destroy the handle
if (StartLine == NULL)
{
Destroy();
return;
}
// Using polyobject linedefs is the only way to track polyobject movements.
// All geometric calculations will be done relative to StartLine.
// Store initial position and angle
StartAngle = VectorAngle(StartLine.Delta.x, StartLine.Delta.y);
VertexStartingPos[0] = VertexLastPos[0] = StartLine.v1.p;
VertexStartingPos[1] = VertexLastPos[1] = StartLine.v2.p;
// Now that the map is loaded, it's safe to call effectors' OnAdd() methods
swwm_PolyobjectEffector e = EffectorList;
if (e != NULL)
{
do
{
e.OnAdd();
e = e.Next;
}
while (e != EffectorList);
}
// Done initializing
IsInitialized = true;
}
override void Tick()
{
// Call PolyTick() for each effector
if (EffectorList != NULL)
{
swwm_PolyobjectEffector e = EffectorList;
do
{
e.PolyTick();
e = e.Next;
}
while (e != EffectorList);
}
// Store current position/angle to be used during the next tic
VertexLastPos[0] = StartLine.v1.p;
VertexLastPos[1] = StartLine.v2.p;
LastAngle = GetAngle();
LastPos = GetPos();
}
override void OnDestroy()
{
// Clean up effectors first
swwm_PolyobjectEffector e = EffectorList;
if (e != NULL)
{
swwm_PolyobjectEffector next;
do
{
next = e.Next;
e.Destroy();
e = next;
}
while (e != EffectorList);
}
}
Sector GetSector()
{
if (StartSector == NULL)
{
Vector2 SpotPos = StartSpotPos;
// Sometimes if StartSpot lies on a one-sided linedef, its position is considered
// out of bounds by GZDoom, which makes Level.PointInSector() produce unexpected
// results. In that case, we need to compensate.
if (!Level.IsPointInLevel((SpotPos, z)))
{
// Look at points in a 5x5 square around the StartSpot
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
SpotPos = StartSpotPos + (x, y);
if (Level.IsPointInLevel((SpotPos, z)))
{
// Found a point within bounds, should be good enough
StartSector = Level.PointInSector(SpotPos);
break;
}
}
if (StartSector)
break;
}
}
else
{
StartSector = Level.PointInSector(SpotPos);
}
}
return StartSector;
}
// Returns initial StartSpot position
Vector2 GetOrigin()
{
return StartSpotPos;
}
// Returns current polyobject angle
double GetAngle()
{
double lineangle = VectorAngle(StartLine.Delta.x, StartLine.Delta.y);
return Actor.DeltaAngle(StartAngle, lineangle);
}
// Returns current polyobject startspot position
Vector2 GetPos()
{
let spotdelta = StartSpotPos - VertexStartingPos[0];
return StartLine.v1.p + Actor.RotateVector(spotdelta, GetAngle());
}
// Returns polyobject coordinates relative to the startspot
Vector2 GetPosDelta()
{
return GetPos() - StartSpotPos;
}
// Returns last polyobject angle
double GetLastAngle()
{
return LastAngle;
}
// Returns last polyobject startspot position
Vector2 GetLastPos()
{
return LastPos;
}
// Returns last coordinates relative to the startspot
Vector2 GetLastPosDelta()
{
return LastPos - StartSpotPos;
}
// Returns current polyobject velocity
Vector2 GetVel()
{
return StartLine.v1.p - VertexLastPos[0];
}
// Returns current polyobject rotation speed
double GetRotationSpeed()
{
return GetAngle() - LastAngle;
}
// Returns whether the polyobject has moved from its spawn position
bool IsAtOrigin()
{
return (VertexStartingPos[0] == StartLine.v1.p && VertexStartingPos[1] == StartLine.v2.p);
}
// Returns whether the polyobject is in motion
bool IsMoving()
{
return (GetPos() != GetLastPos() || GetAngle() != GetLastAngle());
}
// Moves the polyobject to specified location, with specified speed, and plays the
// specified sound of its sound sequence
// (i.e. for a door sound sequence, sndseqmode 0 plays the open sound, 1 plays the
// closing sound)
void MoveTo(Actor activator, Vector2 dest, int Speed, int sndseqmode = 0)
{
// Stop any polyobject movement
Level.ExecuteSpecial(Polyobj_Stop, activator, StartLine, Line.Front, PolyobjectNum);
// Move the polyobject
Level.ExecuteSpecial(Polyobj_OR_MoveTo, activator, StartLine, Line.Front, PolyobjectNum,
Speed, int(dest.x), int(dest.y));
// Polyobj_OR_MoveTo ignores the sound sequence set by the polyobject.
// Play the sound sequence manually inside the sector containing the polyobject.
if (SoundSequenceNum)
{
GetSector().StartSoundSequenceID(CHAN_AUTO, SoundSequenceNum, SeqNode.DOOR, sndseqmode, false);
}
}
}
// Class for iterating over polyobjects
class swwm_PolyobjectIterator: Object
{
private ThinkerIterator it;
static swwm_PolyobjectIterator Create()
{
let it = New('swwm_PolyobjectIterator');
it.it = ThinkerIterator.Create('swwm_PolyobjectHandle');
return it;
}
swwm_PolyobjectHandle Next()
{
return swwm_PolyobjectHandle(it.Next());
}
void Reinit()
{
it.Reinit();
}
}

View file

@ -1,123 +0,0 @@
// Creates a PolyobjectHandle for every polyobject in the map
class swwm_PolyobjectHandlePostProcessor: LevelPostProcessor
{
protected void Apply(Name checksum, String mapname)
{
Array<int> pobjnums;
Array<swwm_PolyobjectHandle> pobjhandles;
// Make sure initialization doesn't happen when reentering a map
if (Level.Time > 0)
return;
// Look for Polyobject StartSpots and create a handle for each
for (uint i = 0; i < GetThingCount(); i++)
{
// Ignore every thing that isn't a Polyobject StartSpot
int ednum = GetThingEdNum(i);
// [MK] hotfix for this to recognize hexen polyobjects
if (gameinfo.gametype&GAME_Hexen)
{
if (ednum == 3001) ednum = swwm_PolyobjectHandle.POTYP_NORMAL;
else if (ednum == 3002) ednum = swwm_PolyobjectHandle.POTYP_CRUSH;
}
if (ednum < swwm_PolyobjectHandle.POTYP_NORMAL || ednum > swwm_PolyobjectHandle.POTYP_HURT)
continue;
// Create a PolyobjectHandle
swwm_PolyobjectHandle handle = swwm_PolyobjectHandle.Create();
// Get polyobject number from StartSpot angle
handle.PolyobjectNum = GetThingAngle(i);
// Store StartSpot position
Vector3 pos = GetThingPos(i);
handle.StartSpotPos = pos.xy;
handle.z = pos.z;
// Store StartSpot type (normal, crush, hurt)
handle.Type = ednum;
// Append polyobject number and corresponding handle to the respective arrays
pobjnums.Push(handle.PolyobjectNum);
pobjhandles.Push(handle);
}
// Look for Polyobj_StartLine/Polyobj_ExplicitLine lines
for (int i = 0; i < Level.Lines.Size(); i++)
{
Line line = Level.Lines[i];
// Ignore every line that doesn't have a Polyobj_StartLine or Polyobj_ExplicitLine
// line special
if (line.Special != Polyobj_StartLine && line.Special != Polyobj_ExplicitLine)
continue;
// Get polyobject number
// (Args[0] for both Polyobj_StartLine and Polyobj_ExplicitLine)
int pobjnum = line.Args[0];
// Find the array index of the corresponding handle
int pobjhandleindex = pobjnums.Find(pobjnum);
if (pobjhandleindex >= pobjnums.Size())
continue; // Polyobject doesn't have a corresponding StartSpot
swwm_PolyobjectHandle handle = pobjhandles[pobjhandleindex];
// Get mirror polyobject number
// (Args[1] for Polyobj_StartLine, Args[2] for Polyobj_ExplicitLine)
int mirrorpobjnum = line.Special == Polyobj_StartLine ? line.Args[1] : line.Args[2];
if (mirrorpobjnum != 0)
{
// Find the array index of the mirror polyobject handle
int mirrorpobjhandleindex = pobjnums.Find(mirrorpobjnum);
if (mirrorpobjhandleindex < pobjnums.Size())
{
// Mirror polyobject handle exists, store it
handle.Mirror = pobjhandles[mirrorpobjhandleindex];
}
}
// Get sound sequence number and store it
// (Args[2] for Polyobj_StartLine, Args[3] for Polyobj_ExplicitLine)
int soundseq = line.Special == Polyobj_StartLine ? line.Args[2] : line.Args[3];
handle.SoundSequenceNum = soundseq;
// Store the line
handle.StartLine = line;
// [MK] the library doesn't store ALL lines belonging to the polyobject, but we need them
handle.Lines.Push(line);
// [MK] collect all connected lines if this is Polyobj_StartLine
if ( line.Special != Polyobj_StartLine )
continue;
bool newlines;
do
{
newlines = false;
for (int j = 0; j < Level.Lines.Size(); j++)
{
Line linea = Level.Lines[j];
if (handle.Lines.Find(linea) < handle.Lines.Size())
continue;
bool nomatches = true;
for (int k = 0; k < handle.Lines.Size(); k++)
{
Line lineb = handle.Lines[k];
if ((linea.v1 != lineb.v1) && (linea.v1 != lineb.v2) && (linea.v2 != lineb.v1) && (linea.v2 != lineb.v2))
continue;
nomatches = false;
break;
}
if (nomatches)
continue;
newlines = true;
handle.Lines.Push(linea);
}
}
while (newlines);
}
}
}

View file

@ -1,3 +0,0 @@
#include "zscript/swwm_Polyobjects/PolyobjectHandle.zs"
#include "zscript/swwm_Polyobjects/PolyobjectMapPostprocessor.zs"
#include "zscript/swwm_Polyobjects/PolyobjectEffector.zs"

View file

@ -1879,7 +1879,7 @@ Class Demolitionist : PlayerPawn
}
SWWMUtility.MarkAchievement("crush",player);
}
private void CheckBreakPolyobject( int dmg )
/*private void CheckBreakPolyobject( int dmg )
{
// see if there are any crushing polyobjects currently "encroaching" the player
Array<Line> touching;
@ -1919,7 +1919,7 @@ Class Demolitionist : PlayerPawn
SWWMUtility.MarkAchievement("crush",player);
}
}
}
}*/
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
// we still have to ENSURE ENTIRELY that this gets nullified (TELEFRAG_DAMAGE overrides damage factors somehow)
@ -1937,7 +1937,7 @@ Class Demolitionist : PlayerPawn
if ( !inflictor && !source )
{
CheckBreakCrusher();
CheckBreakPolyobject(damage);
//CheckBreakPolyobject(damage);
}
// break a spike trap
else if ( source is 'ThrustFloor' )

View file

@ -31,7 +31,7 @@ Class UglyBoyGetsFuckedUp : Thinker
}
// ensures a polyobj stays out of bounds FOREVER
Class SWWMBustedPolyobj : swwm_PolyobjectEffector
/*Class SWWMBustedPolyobj : swwm_PolyobjectEffector
{
Actor whomstdve;
@ -44,7 +44,7 @@ Class SWWMBustedPolyobj : swwm_PolyobjectEffector
Level.ExecuteSpecial(Polyobj_MoveTo,whomstdve,Polyobject.StartLine,Line.Front,Polyobject.PolyobjectNum,int(dist*8),32000,32000);
if ( Polyobject.Mirror ) Level.ExecuteSpecial(Polyobj_Stop,whomstdve,Polyobject.Mirror.StartLine,Line.Front,Polyobject.Mirror.PolyobjectNum);
}
}
}*/
// prevents floors/ceilings from ever moving again, as they're "broken crushers"
Class SWWMCrusherBroken : Thinker

View file

@ -1919,7 +1919,7 @@ Class SWWMUtility
}
// iterate through polyobjects and see if this line is part of one (returning which, if any)
static bool IsPolyLine( Line l, out swwm_PolyobjectHandle o )
/*static bool IsPolyLine( Line l, out swwm_PolyobjectHandle o )
{
let pi = swwm_PolyobjectIterator.Create();
swwm_PolyobjectHandle p;
@ -1931,12 +1931,12 @@ Class SWWMUtility
}
o = null;
return false;
}
}*/
// checks if the specified world coordinate is inside the polyobject
// this check is very naive but it should handle most "normal" shapes
// (yeah, sorry if you somehow want to play this mod with lilith.pk3)
static bool PointInPolyobj( Vector2 p, swwm_PolyobjectHandle o )
/*static bool PointInPolyobj( Vector2 p, swwm_PolyobjectHandle o )
{
// first pass, find which vertex out of all lines is closest
Vertex v = o.StartLine.v1;
@ -1972,7 +1972,7 @@ Class SWWMUtility
}
// is the point behind both lines?
return (PointOnLineSide(p,a) && PointOnLineSide(p,b));
}
}*/
// full reset of inventory (excluding collectibles, and optionally resetting the score)
static play void WipeInventory( Actor mo, bool resetscore = false, bool allplayers = false )

View file

@ -50,7 +50,7 @@ Class BustPoint
Class BusterWall : Thinker
{
Sector hitsector;
swwm_PolyobjectHandle hitpoly;
//swwm_PolyobjectHandle hitpoly;
int accdamage;
Array<int> acchits;
int hitplane;
@ -91,11 +91,11 @@ Class BusterWall : Thinker
private void SpawnDebris( bool initial = false )
{
if ( hitpoly )
/*if ( hitpoly )
{
SpawnDebrisPoly(initial);
return;
}
}*/
double x, y, z;
for ( z=boundsmin.z; z<boundsmax.z; z+=step.z )
for ( y=boundsmin.y; y<boundsmax.y; y+=step.y )
@ -134,7 +134,7 @@ Class BusterWall : Thinker
}
}
private void SpawnDebrisPoly( bool initial = false )
/*private void SpawnDebrisPoly( bool initial = false )
{
for ( int i=0; i<polygrid.Size(); i++ ) for ( double z=boundsmin.z; z<boundsmax.z; z+=step.z )
{
@ -168,7 +168,7 @@ Class BusterWall : Thinker
s.A_SetTranslation('Rubble');
}
}
}
}*/
private static bool IsIOSWall( Line l )
{
@ -275,7 +275,7 @@ Class BusterWall : Thinker
return Bust(faketracer.Results,accdamage,instigator,x,hitz);
}
static bool BustPolyobj( swwm_PolyobjectHandle p, int accdamage, Actor instigator, Vector3 x )
/*static bool BustPolyobj( swwm_PolyobjectHandle p, int accdamage, Actor instigator, Vector3 x )
{
let ti = ThinkerIterator.Create("BusterWall",STAT_USER);
BusterWall iter, bust = null;
@ -391,7 +391,7 @@ Class BusterWall : Thinker
for ( int i=0; i<bust.acchits.Size(); i++ )
SWWMDamNum.Spawn(bust.acchits[i],level.Vec3Offset(bcenter,SWWMUtility.Vec3FromAngles(FRandom[ScoreBits](0,360),FRandom[ScoreBits](-90,90))*8.),'Wallbust');
return true;
}
}*/
static bool Bust( TraceResults d, int accdamage, Actor instigator, Vector3 x, double hitz )
{
@ -402,8 +402,8 @@ Class BusterWall : Thinker
if ( d.HitType == TRACE_HitWall )
{
// check if it's a polyobject line, if so, switch to the other bust method
swwm_PolyObjectHandle p;
if ( SWWMUtility.IsPolyLine(d.HitLine,p) ) return BustPolyobj(p,accdamage,instigator,x);
//swwm_PolyObjectHandle p;
//if ( SWWMUtility.IsPolyLine(d.HitLine,p) ) return BustPolyobj(p,accdamage,instigator,x);
// no busting the goat
if ( IsIOSWall(d.HitLine) ) return false;
// onesided wall? no bust