//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id: MainGameInfo.vc 1819 2006-10-24 19:54:18Z dj_jl $ //** //** Copyright (C) 1999-2006 Jānis Legzdiņš //** //** This program is free software; you can redistribute it and/or //** modify it under the terms of the GNU General Public License //** as published by the Free Software Foundation; either version 2 //** of the License, or (at your option) any later version. //** //** This program is distributed in the hope that it will be useful, //** but WITHOUT ANY WARRANTY; without even the implied warranty of //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //** GNU General Public License for more details. //** //************************************************************************** class LineSpecialGameInfo : GameInfo; // Thing types that are handled durign set-up of a level. const int FLOOR_SLOPE_TYPE = 1500, CEILING_SLOPE_TYPE = 1501, FLOOR_VERTEX_HEIGHT_TYPE = 1504, CEILING_VERTEX_HEIGHT_TYPE = 1505, PO_ANCHOR_TYPE_HEXEN = 3000, PO_SPAWN_TYPE_HEXEN = 3001, PO_SPAWNCRUSH_TYPE_HEXEN = 3002, PO_ANCHOR_TYPE = 9300, PO_SPAWN_TYPE = 9301, PO_SPAWNCRUSH_TYPE = 9302, SLOPE_FLOOR_POINT_LINE_TYPE = 9500, SLOPE_CEILING_POINT_LINE_TYPE = 9501, SET_FLOOR_SLOPE_TYPE = 9502, SET_CEILING_SLOPE_TYPE = 9503, COPY_FLOOR_PLANE_TYPE = 9510, COPY_CEILING_PLANE_TYPE = 9511; float contents_alpha[9]; bool bUseHexenPolyobjTypes; // -- Flags for actor behavior -- // In Doom non-clipping missiles doesn't explode when hitting the floor, // in other games they do. bool bNoClipIgnoreFloor; // Use blood splatter like in Raven games. bool bBloodSplatter; // Don't do damage thrust to the invulnerable players bool bNoDamageThrustInvulnerable; // Monsters move faster in nightmare mode. bool bNightmareFastChase; // Use pickup respawn effects like in Raven's games. bool bRavenStylePickupRespawn; // Give double ammo in baby and nightmare skills bool bBabyNightmareDoubleAmmo; // Wether to give extra ammo in nightmare mode bool bNightmareExtraAmmo; // Always to switch to a newly picked up weapon. bool bAlwaysSwitchNewWeapon; // Randomise blood's initial state time bool bBloodRandomiseTime; // Enter blood's spray state bool bBloodSpray; // Ripper blood has no gravity bool bRipperBloodNoGravity; bool bDehacked; bool respawnmonsters; bool bRespawnItems; bool bRespawnBigItems; bool bWeaponsStay; float windTab[3]; float pushTab[5]; int opposite[9]; int diags[4]; float xspeed[8]; float yspeed[8]; float air_control; float TeleFogHeight; class TeleportFogClass; float DefaultKickBack; class BloodClass; class BloodSplatterClass; class AxeBloodClass; int NonMonsterAngleIncrements; int InvDefaultMaxAmount; int DefaultInvulnBlendColour; float IceMoveFactor; int ramp1[16]; int ramp2[16]; int GameFilterFlag; //========================================================================== // // MakeSlope // //========================================================================== void MakeSlope(Level InLevel, mthing_t* mthing, bool IsCeiling) { sector_t* sec; line_t* line; int i; sec_plane_t* plane; sec = InLevel.PointInSector(vector(mthing->x, mthing->y, 0.0)); for (i = 0; i < sec->linecount; i++) { line = sec->lines[i]; if (mthing->tid == line->arg1) { TVec v1; TVec v2; TVec p1; TVec p2; TVec p3; if (!IsCeiling) { plane = &sec->floor; p1 = vector(line->v1->x, line->v1->y, plane->minz); p2 = vector(line->v2->x, line->v2->y, plane->minz); } else { plane = &sec->ceiling; p1 = vector(line->v1->x, line->v1->y, plane->maxz); p2 = vector(line->v2->x, line->v2->y, plane->maxz); } p3 = vector(mthing->x, mthing->y, mthing->height); if (PointOnPlaneSide(p3, line) == IsCeiling) { v1 = p2 - p3; v2 = p1 - p3; } else { v1 = p1 - p3; v2 = p2 - p3; } plane->normal = Normalise(CrossProduct(v1, v2)); if (!IsCeiling && plane->normal.z <= 0.0) { Error("Floor with normal.z <= 0.0"); } else if (IsCeiling && plane->normal.z >= 0.0) { Error("Ceiling with normal.z >= 0.0"); } plane->dist = DotProduct(plane->normal, p3); return; } } } //=========================================================================== // // SlopeLineToPoint // //=========================================================================== void SlopeLineToPoint(Level InLevel, mthing_t* mthing, bool IsCeiling) { sector_t* sec; sec_plane_t* plane; TVec p1; TVec p2; int i; TVec v1; TVec v2; TVec cross; sec = InLevel.PointInSector(vector(mthing->x, mthing->y, 0.0)); if (!IsCeiling) { plane = &sec->floor; } else { plane = &sec->ceiling; } p1 = vector(mthing->x, mthing->y, 0.0); p1.z = GetPlanePointZ(plane, p1) + mthing->height; for (i = 0; i < InLevel.NumLines; i++) { line_t* line = &InLevel.Lines[i]; if (line->LineTag != mthing->arg1) { continue; } if (PointOnPlaneSide(p1, line) == 0) { sec = line->frontsector; } else { sec = line->backsector; } if (sec == NULL) { continue; } if (!IsCeiling) { plane = &sec->floor; } else { plane = &sec->ceiling; } p2 = *line->v1; p2.z = GetPlanePointZ(plane, p2); v1 = *line->v2 - *line->v1; v1.z = GetPlanePointZ(plane, *line->v2) - p2.z; v2 = p1 - *line->v1; v2.z = p1.z - p2.z; cross = CrossProduct(v1, v2); float len = Length(cross); if (len == 0.0) { print("Slope thing at (%d,%d) lies directly on its target line.\n", mthing->x, mthing->y); return; } cross = cross / len; // Fix backward normals if ((cross.z < 0.0 && !IsCeiling) || (cross.z > 0.0 && IsCeiling)) { cross = -cross; } plane->normal = cross; plane->dist = DotProduct(plane->normal, p1); } } //=========================================================================== // // SetSlope // //=========================================================================== void SetSlope(Level InLevel, mthing_t* mthing, bool IsCeiling) { TVec p1; sec_plane_t* plane; sector_t* sec; float xyang; float zang; TVec norm; sec = InLevel.PointInSector(vector(mthing->x, mthing->y, 0.0)); if (!IsCeiling) { plane = &sec->floor; } else { plane = &sec->ceiling; } p1 = vector(mthing->x, mthing->y, 0.0); p1.z = GetPlanePointZ(plane, p1) + mthing->height; if (mthing->arg1 >= 180) { zang = 179.0; } else if (mthing->arg1 <= 0) { zang = 1.0; } else { zang = itof(mthing->arg1); } if (IsCeiling) { zang += 180.0; } xyang = itof(mthing->angle); norm.x = cos(zang) * cos(xyang); norm.y = cos(zang) * sin(xyang); norm.z = sin(zang); norm = Normalise(norm); plane->normal = norm; plane->dist = DotProduct(plane->normal, p1); } //========================================================================== // // SetVertexHeights // //========================================================================== bool SetVertexHeights(Level InLevel, int ThingID) { int i; int j; bool ret; mthing_t * mthing; ret = false; // Clean all for (i = 0; i < InLevel.NumVertexes; i++) { InLevel.Vertexes[i].z = 0.1; } for (j = 0; j < InLevel.NumThings; j++) { mthing = &InLevel.Things[j]; if (mthing->type == ThingID) { for (i = 0; i < InLevel.NumVertexes; i++) { if (InLevel.Vertexes[i].x == mthing->x && InLevel.Vertexes[i].y == mthing->y) { InLevel.Vertexes[i].z = mthing->height; ret = true; } } } } return ret; } //========================================================================== // // CleanVertexHeights // //========================================================================== void CleanVertexHeights(Level InLevel) { int i; for (i = 0; i < InLevel.NumVertexes; i++) { InLevel.Vertexes[i].z = 0.0; } } //========================================================================== // // MakeVertexFloorHeights // //========================================================================== void MakeVertexFloorHeights(Level InLevel) { int i; sector_t *sec; TVec p1; TVec p2; TVec p3; TVec v1; TVec v2; if (!SetVertexHeights(InLevel, FLOOR_VERTEX_HEIGHT_TYPE)) { return; } for (i = 0; i < InLevel.NumSectors; i++) { sec = &InLevel.Sectors[i]; if (sec->linecount != 3) continue; p1 = *sec->lines[0]->v1; p2 = *sec->lines[0]->v2; if (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2) { p3 = *sec->lines[1]->v2; } else { p3 = *sec->lines[1]->v1; } if (p1.z == 0.1 && p2.z == 0.1 && p3.z == 0.1) { continue; } if (p1.z == 0.1) { p1.z = sec->floorheight; } if (p2.z == 0.1) { p2.z = sec->floorheight; } if (p3.z == 0.1) { p3.z = sec->floorheight; } if (PointOnPlaneSide(p3, sec->lines[0]) == 0) { v1 = p2 - p3; v2 = p1 - p3; } else { v1 = p1 - p3; v2 = p2 - p3; } sec->floor.normal = Normalise(CrossProduct(v1, v2)); if (sec->floor.normal.z <= 0.0) { Error("Floor with normal.z <= 0.0"); } sec->floor.dist = DotProduct(sec->floor.normal, p3); } } //========================================================================== // // MakeVertexCeilingHeights // //========================================================================== void MakeVertexCeilingHeights(Level InLevel) { int i; sector_t *sec; TVec p1; TVec p2; TVec p3; TVec v1; TVec v2; if (!SetVertexHeights(InLevel, CEILING_VERTEX_HEIGHT_TYPE)) { return; } for (i = 0; i < InLevel.NumSectors; i++) { sec = &InLevel.Sectors[i]; if (sec->linecount != 3) continue; p1 = *sec->lines[0]->v1; p2 = *sec->lines[0]->v2; if (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2) { p3 = *sec->lines[1]->v2; } else { p3 = *sec->lines[1]->v1; } if (p1.z == 0.1 && p2.z == 0.1 && p3.z == 0.1) { continue; } if (p1.z == 0.1) { p1.z = sec->ceilingheight; } if (p2.z == 0.1) { p2.z = sec->ceilingheight; } if (p3.z == 0.1) { p3.z = sec->ceilingheight; } if (PointOnPlaneSide(p3, sec->lines[0]) == 0) { v1 = p1 - p3; v2 = p2 - p3; } else { v1 = p2 - p3; v2 = p1 - p3; } sec->ceiling.normal = Normalise(CrossProduct(v1, v2)); if (sec->ceiling.normal.z >= 0.0) { Error("Ceiling with normal.z >= 0.0"); } sec->ceiling.dist = DotProduct(sec->ceiling.normal, p3); } } //========================================================================== // // AlignPlane // // Set slopes for sectors, based on line specials // // Aligns the floor or ceiling of a sector to the corresponding plane // on the other side of the reference line. (By definition, line must be // two-sided.) // // If (which & 1), sets floor. // If (which & 2), sets ceiling. // //========================================================================== void AlignPlane(Level InLevel, sector_t *sec, line_t *line, int which) { sector_t *refsec; float bestdist; TVec *refvert = (*sec->lines)->v1; int i; line_t **probe; float dist; TVec *vert; TVec p, v1, v2, cross; sec_plane_t *refplane; sec_plane_t *srcplane; float srcheight, destheight; if (line->backsector == NULL) return; // Find furthest vertex from the reference line. It, along with the two // ends of the line will define the plane. bestdist = 0.0; for (i = sec->linecount * 2, probe = sec->lines; i > 0; i--) { if (i & 1) { vert = (*probe)->v2; probe = &probe[1]; } else vert = (*probe)->v1; dist = fabs(DotProduct(*vert, line->normal) - line->dist); if (dist > bestdist) { bestdist = dist; refvert = vert; } } refsec = line->frontsector == sec ? line->backsector : line->frontsector; p = *line->v1; v1 = *line->v2 - *line->v1; v2 = *refvert - *line->v1; refplane = (which == 0) ? &refsec->floor : &refsec->ceiling; srcplane = (which == 0) ? &sec->floor : &sec->ceiling; srcheight = (which == 0) ? sec->floorheight : sec->ceilingheight; destheight = (which == 0) ? refsec->floorheight : refsec->ceilingheight; p.z = destheight; v1.z = 0.0; v2.z = srcheight - destheight; cross = Normalise(CrossProduct(v1, v2)); // Fix backward normals if ((cross.z < 0.0 && which == 0) || (cross.z > 0.0 && which == 1)) { cross = -cross; } srcplane->normal = cross; srcplane->dist = DotProduct(cross, p); } //========================================================================== // // SetSlopes // //========================================================================== void SetSlopes(Level InLevel) { int i, s; for (i = 0; i < InLevel.NumLines; i++) { if (InLevel.Lines[i].special == LNSPEC_PlaneAlign) { InLevel.Lines[i].special = 0; InLevel.Lines[i].LineTag = InLevel.Lines[i].arg3; if (InLevel.Lines[i].backsector != NULL) { // args[0] is for floor, args[1] is for ceiling // // As a special case, if args[1] is 0, // then args[0], bits 2-3 are for ceiling. for (s = 0; s < 2; s++) { int bits = (s == 0 ? InLevel.Lines[i].arg1 : InLevel.Lines[i].arg2) & 3; if (s == 1 && bits == 0) bits = (InLevel.Lines[i].arg1 >> 2) & 3; if (bits == 1) // align front side to back AlignPlane(InLevel, InLevel.Lines[i].frontsector, &InLevel.Lines[i], s); else if (bits == 2) // align back side to front AlignPlane(InLevel, InLevel.Lines[i].backsector, &InLevel.Lines[i], s); } } } } } //=========================================================================== // // CopyPlane // //=========================================================================== void CopyPlane(Level InLevel, mthing_t* mthing, bool IsCeiling) { sector_t* dst; sector_t* src; int secnum; dst = InLevel.PointInSector(vector(mthing->x, mthing->y, 0.0)); secnum = InLevel.FindSectorFromTag(mthing->arg1, -1); if (secnum == -1) { return; } src = &InLevel.Sectors[secnum]; if (!IsCeiling) { dst->floor.normal = src->floor.normal; dst->floor.dist = src->floor.dist; } else { dst->ceiling.normal = src->ceiling.normal; dst->ceiling.dist = src->ceiling.dist; } } //========================================================================== // // SpawnExtraFloors // //========================================================================== void SpawnExtraFloors(Level InLevel, line_t * line) { int j; for (j = 0; j < InLevel.NumSectors; j++) { if (line->arg1 == InLevel.Sectors[j].tag) { InLevel.AddExtraFloor(line, &InLevel.Sectors[j]); } } } //========================================================================== // // MakeContents // //========================================================================== void MakeContents(line_t * line) { int contents; if (!line->arg1 && !line->arg2 && !line->arg3) { contents = 1;//CONTENTS_WATER; line->frontsector->params.contents = contents; if (line->frontsector->floor.dist == -line->frontsector->ceiling.dist) { line->frontsector->floor.Alpha = contents_alpha[contents]; line->frontsector->ceiling.Alpha = contents_alpha[contents]; line->frontsector->ceiling.flags |= SPF_NOBLOCKING | SPF_NOBLOCKSIGHT | SPF_NOBLOCKSHOOT; line->frontsector->floor.flags |= SPF_NOBLOCKING | SPF_NOBLOCKSIGHT | SPF_NOBLOCKSHOOT; } } else { line->frontsector->params.contents = line->arg1; line->frontsector->floor.Alpha = (100.0 - itof(line->arg2)) / 100.0; line->frontsector->ceiling.Alpha = (100.0 - itof(line->arg2)) / 100.0; line->frontsector->ceiling.flags = line->arg3; line->frontsector->floor.flags = line->arg3; } } //========================================================================== // // MakeHeightSec // // killough 3/7/98: // support for drawn heights coming from different sector // //========================================================================== void MakeHeightSec(Level InLevel, line_t* Line) { sector_t* Sec; int s; Sec = Line->frontsector; Sec->bTransferSource = true; if (Line->arg2 & 2) { Sec->bFakeFloorOnly = true; } if (Line->arg2 & 4) { Sec->bClipFakePlanes = true; } if (Line->arg2 & 8) { Sec->bUnderWater = true; } if (Line->arg2 & 16) { Sec->bIgnoreHeightSec = true; } if (Line->arg2 & 32) { Sec->bNoFakeLight = true; } for (s = InLevel.FindSectorFromTag(Line->arg1, -1); s >= 0; s = InLevel.FindSectorFromTag(Line->arg1, s)) { InLevel.Sectors[s].heightsec = Sec; InLevel.SetHeightSector(&InLevel.Sectors[s], Sec, Line->arg2); } } //========================================================================== // // SetSectorFriction // //========================================================================== void SetSectorFriction(Level InLevel, int tag, int amount, bool alterFlag) { int s; int OldFriction; int OldMoveFactor; float Friction; float MoveFactor; // An amount of 100 should result in a friction of // ORIG_FRICTION (0xE800) OldFriction = (0x1EB8 * amount) / 0x80 + 0xD001; // killough 8/28/98: prevent odd situations if (OldFriction > 0x10000) OldFriction = 0x10000; if (OldFriction < 0) OldFriction = 0; // The following check might seem odd. At the time of movement, // the move distance is multiplied by 'friction/0x10000', so a // higher friction value actually means 'less friction'. // [RH] Twiddled these values so that momentum on ice (with // friction 0xf900) is the same as in Heretic/Hexen. if (OldFriction >= 0xe800) // ice // movefactor = ((0x10092 - friction)*(0x70))/0x158; OldMoveFactor = ((0x10092 - OldFriction) * 1024) / 4352 + 568; else OldMoveFactor = ((OldFriction - 0xDB34) * (0xA)) / 0x80; // killough 8/28/98: prevent odd situations if (OldMoveFactor < 32) OldMoveFactor = 32; Friction = (1.0 - itof(OldFriction) / itof(0x10000)) * 35.0; MoveFactor = itof(OldMoveFactor) / itof(0x10000); for (s = InLevel.FindSectorFromTag(tag, -1); s >= 0; s = InLevel.FindSectorFromTag(tag, s)) { // killough 8/28/98: // // Instead of spawning thinkers, which are slow and expensive, // modify the sector's own friction values. Friction should be // a property of sectors, not objects which reside inside them. // Original code scanned every object in every friction sector // on every tic, adjusting its friction, putting unnecessary // drag on CPU. New code adjusts friction of sector only once // at level startup, and then uses this friction value. InLevel.Sectors[s].Friction = Friction; InLevel.Sectors[s].MoveFactor = MoveFactor; if (alterFlag) { // When used inside a script, the sectors' friction flags // can be enabled and disabled at will. if (OldFriction == 0xe800) { InLevel.Sectors[s].special &= ~SECSPEC_FRICTION_MASK; } else { InLevel.Sectors[s].special |= SECSPEC_FRICTION_MASK; } } } } //========================================================================== // // SpawnWorld // //========================================================================== void SpawnWorld(Level InLevel) { int i; int j; int length; int SecNum; float alpha; mthing_t* mthing; line_t* line; // Set up tagged lines. for (i = 0; i < InLevel.NumLines; i++) { line = &InLevel.Lines[i]; switch (line->special) { case LNSPEC_LineSetIdentification: line->special = 0; case LNSPEC_LineTranslucent: case LNSPEC_TeleportLine: if (line->arg1) { line->LineTag = line->arg1; } break; } } // Spawn slopes. SetSlopes(InLevel); for (i = 0; i < InLevel.NumThings; i++) { mthing = &InLevel.Things[i]; switch (mthing->type) { case FLOOR_SLOPE_TYPE: MakeSlope(InLevel, mthing, false); mthing->type = 0; break; case CEILING_SLOPE_TYPE: MakeSlope(InLevel, mthing, true); mthing->type = 0; break; case SLOPE_FLOOR_POINT_LINE_TYPE: SlopeLineToPoint(InLevel, mthing, false); mthing->type = 0; break; case SLOPE_CEILING_POINT_LINE_TYPE: SlopeLineToPoint(InLevel, mthing, true); mthing->type = 0; break; case SET_FLOOR_SLOPE_TYPE: SetSlope(InLevel, mthing, false); mthing->type = 0; break; case SET_CEILING_SLOPE_TYPE: SetSlope(InLevel, mthing, true); mthing->type = 0; break; } } MakeVertexFloorHeights(InLevel); MakeVertexCeilingHeights(InLevel); CleanVertexHeights(InLevel); for (i = 0; i < InLevel.NumThings; i++) { mthing = &InLevel.Things[i]; if (mthing->type == COPY_FLOOR_PLANE_TYPE || mthing->type == COPY_CEILING_PLANE_TYPE) { CopyPlane(InLevel, mthing, mthing->type & 1); mthing->type = 0; } } // Initialise initial friction values. for (i = 0; i < InLevel.NumSectors; i++) { InLevel.Sectors[i].Friction = EntityEx::FRICTION_NORMAL; } // Set up 3D floors, transfers of light, etc. for (i = 0; i < InLevel.NumLines; i++) { line = &InLevel.Lines[i]; switch (line->special) { case LNSPEC_3DFloor: SpawnExtraFloors(InLevel, line); line->special = 0; break; case LNSPEC_Contents: MakeContents(line); line->special = 0; break; case LNSPEC_TransferFloorLight: for (SecNum = InLevel.FindSectorFromTag(line->arg1, -1); SecNum >= 0; SecNum = InLevel.FindSectorFromTag(line->arg1, SecNum)) { InLevel.SetFloorLightSector(&InLevel.Sectors[SecNum], line->frontsector); } line->special = 0; line->frontsector->bTransferSource = true; break; case LNSPEC_TransferCeilingLight: for (SecNum = InLevel.FindSectorFromTag(line->arg1, -1); SecNum >= 0; SecNum = InLevel.FindSectorFromTag(line->arg1, SecNum)) { InLevel.SetCeilingLightSector(&InLevel.Sectors[SecNum], line->frontsector); } line->special = 0; line->frontsector->bTransferSource = true; break; case LNSPEC_SectorSetFriction: if (line->arg2) { // Allow setting friction amount from parameter length = line->arg2 <= 200 ? line->arg2 : 200; } else { length = ftoi(Length(*line->v2 - *line->v1)); } SetSectorFriction(InLevel, line->arg1, length, false); line->special = 0; break; case LNSPEC_TransferHeights: MakeHeightSec(InLevel, line); line->special = 0; break; } } // Process translucent lines for (i = 0; i < InLevel.NumLines; i++) { line = &InLevel.Lines[i]; switch (line->special) { case LNSPEC_LineTranslucent: alpha = itof(line->arg2) / 255.0; if (line->arg1) { for (j = 0; j < InLevel.NumLines; j++) { if (InLevel.Lines[j].LineTag == line->arg1) { InLevel.Lines[j].alpha = alpha; } } } else { line->alpha = alpha; } line->special = 0; break; case 49: if (line->arg2 != 255) { line->alpha = itof(line->arg2) / 255.0; } break; } } // Spawn polyobjects. for (i = 0; i < InLevel.NumThings; i++) { mthing = &InLevel.Things[i]; switch (mthing->type) { case PO_SPAWN_TYPE_HEXEN: case PO_SPAWNCRUSH_TYPE_HEXEN: if (!bUseHexenPolyobjTypes) { break; } case PO_SPAWN_TYPE: case PO_SPAWNCRUSH_TYPE: // Polyobj StartSpot Pt. InLevel.SpawnPolyobj(mthing->x, mthing->y, mthing->angle, mthing->type == PO_SPAWNCRUSH_TYPE_HEXEN || mthing->type == PO_SPAWNCRUSH_TYPE); mthing->type = 0; break; case PO_ANCHOR_TYPE_HEXEN: if (!bUseHexenPolyobjTypes) { break; } case PO_ANCHOR_TYPE: // Polyobj Anchor Pt. InLevel.AddPolyAnchorPoint(mthing->x, mthing->y, mthing->angle); mthing->type = 0; break; } } } defaultproperties { contents_alpha[0] = 1.0; contents_alpha[1] = 0.5; contents_alpha[2] = 0.8; contents_alpha[3] = 0.6; contents_alpha[4] = 0.55; contents_alpha[5] = 0.7; contents_alpha[6] = 0.85; contents_alpha[7] = 0.7; contents_alpha[8] = 0.7; windTab[0] = 5.0 / 32.0; windTab[1] = 10.0 / 32.0; windTab[2] = 25.0 / 32.0; pushTab[0] = 5.0 * 35.0 * 35.0 / 32.0; pushTab[1] = 10.0 * 35.0 * 35.0 / 32.0; pushTab[2] = 25.0 * 35.0 * 35.0 / 32.0; pushTab[3] = 30.0 * 35.0 * 35.0 / 32.0; pushTab[4] = 35.0 * 35.0 * 35.0 / 32.0; opposite[0] = DI_WEST; opposite[1] = DI_SOUTHWEST; opposite[2] = DI_SOUTH; opposite[3] = DI_SOUTHEAST; opposite[4] = DI_EAST; opposite[5] = DI_NORTHEAST; opposite[6] = DI_NORTH; opposite[7] = DI_NORTHWEST; opposite[8] = DI_NODIR; diags[0] = DI_NORTHWEST; diags[1] = DI_NORTHEAST; diags[2] = DI_SOUTHWEST; diags[3] = DI_SOUTHEAST; xspeed[0] = 1.0; xspeed[1] = 0.7171630859; xspeed[2] = 0.0; xspeed[3] = -0.7171630859; xspeed[4] = -1.0; xspeed[5] = -0.7171630859; xspeed[6] = 0.0; xspeed[7] = 0.7171630859; yspeed[0] = 0.0; yspeed[1] = 0.7171630859; yspeed[2] = 1.0; yspeed[3] = 0.7171630859; yspeed[4] = 0.0; yspeed[5] = -0.7171630859; yspeed[6] = -1.0; yspeed[7] = -0.7171630859; ramp1[0] = 0xfffff31b; ramp1[1] = 0xefdfab27; ramp1[2] = 0xdfbf772f; ramp1[3] = 0xcf9f4f33; ramp1[4] = 0xbf7f3b2b; ramp1[5] = 0xaf632f1f; ramp1[6] = 0x9f4b2313; ramp1[7] = 0x8f2f170b; ramp1[8] = 0x7f7f3b2b; ramp1[9] = 0x6f632f1f; ramp1[10] = 0x5f4b2313; ramp1[11] = 0x4f2f170b; ramp1[12] = 0x3f7f3b2b; ramp1[13] = 0x2f632f1f; ramp1[14] = 0x1f4b2313; ramp1[15] = 0x0f2f170b; ramp2[0] = 0xfffff31b; ramp2[1] = 0xefefcb1f; ramp2[2] = 0xdfdfab27; ramp2[3] = 0xcfcf8f2b; ramp2[4] = 0xbfbf772f; ramp2[5] = 0xafaf632f; ramp2[6] = 0x9f8f4333; ramp2[7] = 0x8f733723; ramp2[8] = 0x7fbf772f; ramp2[9] = 0x6faf632f; ramp2[10] = 0x5f8f4333; ramp2[11] = 0x4f733723; ramp2[12] = 0x3fbf772f; ramp2[13] = 0x2faf632f; ramp2[14] = 0x1f8f4333; ramp2[15] = 0x0f733723; air_control = 1.0 / 256.0; NonMonsterAngleIncrements = 45; bNightmareExtraAmmo = true; InvDefaultMaxAmount = 25; IceMoveFactor = 0.5; }