// // R_SlopeLights // static void R_SlopeLights(int len, double startcmap, double endcmap) { int i; fixed_t map, map2, step; if(plane.fixedcolormap) { for(i = 0; i < len; i++) slopespan.colormap[i] = plane.fixedcolormap; return; } map = M_FloatToFixed((startcmap / 256.0 * NUMCOLORMAPS)); map2 = M_FloatToFixed((endcmap / 256.0 * NUMCOLORMAPS)); if(len > 1) step = (map2 - map) / (len - 1); else step = 0; for(i = 0; i < len; i++) { int index = (int)(map >> FRACBITS) + 1; index -= (extralight * LIGHTBRIGHT); if(index < 0) slopespan.colormap[i] = (byte *)(plane.colormap); else if(index >= NUMCOLORMAPS) slopespan.colormap[i] = (byte *)(plane.colormap + ((NUMCOLORMAPS - 1) * 256)); else slopespan.colormap[i] = (byte *)(plane.colormap + (index * 256)); map += step; } }
// // P_MakeSlope // // Alocates and fill the contents of a slope structure. // static pslope_t *P_MakeSlope(const v3float_t *o, const v2float_t *d, const float zdelta, bool isceiling) { pslope_t *ret = (pslope_t *)(Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL)); memset(ret, 0, sizeof(*ret)); ret->o.x = M_FloatToFixed(ret->of.x = o->x); ret->o.y = M_FloatToFixed(ret->of.y = o->y); ret->o.z = M_FloatToFixed(ret->of.z = o->z); ret->d.x = M_FloatToFixed(ret->df.x = d->x); ret->d.y = M_FloatToFixed(ret->df.y = d->y); ret->zdelta = M_FloatToFixed(ret->zdeltaf = zdelta); { v3float_t v1, v2, v3, d1, d2; float len; v1.x = o->x; v1.y = o->y; v1.z = o->z; v2.x = v1.x; v2.y = v1.y + 10.0f; v2.z = P_GetZAtf(ret, v2.x, v2.y); v3.x = v1.x + 10.0f; v3.y = v1.y; v3.z = P_GetZAtf(ret, v3.x, v3.y); if(isceiling) { M_SubVec3f(&d1, &v1, &v3); M_SubVec3f(&d2, &v2, &v3); } else { M_SubVec3f(&d1, &v1, &v2); M_SubVec3f(&d2, &v3, &v2); } M_CrossProduct3f(&ret->normalf, &d1, &d2); len = (float)sqrt(ret->normalf.x * ret->normalf.x + ret->normalf.y * ret->normalf.y + ret->normalf.z * ret->normalf.z); ret->normalf.x /= len; ret->normalf.y /= len; ret->normalf.z /= len; } return ret; }
// // ACS_ChkThingVar // bool ACS_ChkThingVar(Mobj *thing, uint32_t var, int32_t val) { if(!thing) return false; switch(var) { case ACS_THINGVAR_Health: return thing->health == val; case ACS_THINGVAR_Speed: return thing->info->speed == val; case ACS_THINGVAR_Damage: return thing->damage == val; case ACS_THINGVAR_Alpha: return thing->translucency == val; case ACS_THINGVAR_RenderStyle: return false; case ACS_THINGVAR_SeeSound: return false; case ACS_THINGVAR_AttackSound: return false; case ACS_THINGVAR_PainSound: return false; case ACS_THINGVAR_DeathSound: return false; case ACS_THINGVAR_ActiveSound: return false; case ACS_THINGVAR_Ambush: return !!(thing->flags & MF_AMBUSH) == !!val; case ACS_THINGVAR_Invulnerable: return !!(thing->flags2 & MF2_INVULNERABLE) == !!val; case ACS_THINGVAR_JumpZ: return false; case ACS_THINGVAR_ChaseGoal: return false; case ACS_THINGVAR_Frightened: return false; case ACS_THINGVAR_Friendly: return !!(thing->flags & MF_FRIEND) == !!val; case ACS_THINGVAR_SpawnHealth: return thing->info->spawnhealth == val; case ACS_THINGVAR_Dropped: return !!(thing->flags & MF_DROPPED) == !!val; case ACS_THINGVAR_NoTarget: return false; case ACS_THINGVAR_Species: return false; case ACS_THINGVAR_NameTag: return false; case ACS_THINGVAR_Score: return false; case ACS_THINGVAR_NoTrigger: return false; case ACS_THINGVAR_DamageFactor: return false; case ACS_THINGVAR_MasterTID: return false; case ACS_THINGVAR_TargetTID: return thing->target ? thing->target->tid == val : false; case ACS_THINGVAR_TracerTID: return thing->tracer ? thing->tracer->tid == val : false; case ACS_THINGVAR_WaterLevel: return false; case ACS_THINGVAR_ScaleX: return M_FloatToFixed(thing->xscale) == val; case ACS_THINGVAR_ScaleY: return M_FloatToFixed(thing->yscale) == val; case ACS_THINGVAR_Dormant: return !!(thing->flags2 & MF2_DORMANT) == !!val; case ACS_THINGVAR_Mass: return thing->info->mass == val; case ACS_THINGVAR_Accuracy: return false; case ACS_THINGVAR_Stamina: return false; case ACS_THINGVAR_Height: return thing->height == val; case ACS_THINGVAR_Radius: return thing->radius == val; case ACS_THINGVAR_ReactionTime: return thing->reactiontime == val; case ACS_THINGVAR_MeleeRange: return MELEERANGE == val; case ACS_THINGVAR_ViewHeight: return false; case ACS_THINGVAR_AttackZOff: return false; case ACS_THINGVAR_StencilColor: return false; case ACS_THINGVAR_Friction: return false; case ACS_THINGVAR_DamageMult: return false; case ACS_THINGVAR_Angle: return thing->angle >> 16 == (uint32_t)val; case ACS_THINGVAR_Armor: return thing->player ? thing->player->armorpoints == val : false; // ioanch 20160116: extreme sector (portal aware) case ACS_THINGVAR_CeilingTexture: return P_ExtremeSectorAtPoint(thing, true)->ceilingpic == R_FindWall(ACSVM::GetString(val)); case ACS_THINGVAR_CeilingZ: return thing->ceilingz == val; case ACS_THINGVAR_FloorTexture: return P_ExtremeSectorAtPoint(thing, false)->floorpic == R_FindWall(ACSVM::GetString(val)); case ACS_THINGVAR_FloorZ: return thing->floorz == val; case ACS_THINGVAR_Frags: return thing->player ? thing->player->totalfrags == val : false; case ACS_THINGVAR_LightLevel: return thing->subsector->sector->lightlevel == val; case ACS_THINGVAR_MomX: return thing->momx == val; case ACS_THINGVAR_MomY: return thing->momy == val; case ACS_THINGVAR_MomZ: return thing->momz == val; case ACS_THINGVAR_Pitch: return thing->player ? thing->player->pitch >> 16 == val : false; case ACS_THINGVAR_PlayerNumber: return thing->player ? thing->player - players == val : false; case ACS_THINGVAR_SigilPieces: return false; case ACS_THINGVAR_TID: return thing->tid == val; case ACS_THINGVAR_Type: return thing->type == E_ThingNumForName(ACSVM::GetString(val)); case ACS_THINGVAR_X: return thing->x == val; case ACS_THINGVAR_Y: return thing->y == val; case ACS_THINGVAR_Z: return thing->z == val; default: return false; } }
// // ACS_GetThingVar // int32_t ACS_GetThingVar(Mobj *thing, uint32_t var) { if(!thing) return 0; switch(var) { case ACS_THINGVAR_Health: return thing->health; case ACS_THINGVAR_Speed: return thing->info->speed; case ACS_THINGVAR_Damage: return thing->damage; case ACS_THINGVAR_Alpha: return thing->translucency; case ACS_THINGVAR_RenderStyle: return 0; case ACS_THINGVAR_SeeSound: return 0; case ACS_THINGVAR_AttackSound: return 0; case ACS_THINGVAR_PainSound: return 0; case ACS_THINGVAR_DeathSound: return 0; case ACS_THINGVAR_ActiveSound: return 0; case ACS_THINGVAR_Ambush: return !!(thing->flags & MF_AMBUSH); case ACS_THINGVAR_Invulnerable: return !!(thing->flags2 & MF2_INVULNERABLE); case ACS_THINGVAR_JumpZ: return 0; case ACS_THINGVAR_ChaseGoal: return 0; case ACS_THINGVAR_Frightened: return 0; case ACS_THINGVAR_Friendly: return !!(thing->flags & MF_FRIEND); case ACS_THINGVAR_SpawnHealth: return thing->info->spawnhealth; case ACS_THINGVAR_Dropped: return !!(thing->flags & MF_DROPPED); case ACS_THINGVAR_NoTarget: return 0; case ACS_THINGVAR_Species: return 0; case ACS_THINGVAR_NameTag: return 0; case ACS_THINGVAR_Score: return 0; case ACS_THINGVAR_NoTrigger: return 0; case ACS_THINGVAR_DamageFactor: return 0; case ACS_THINGVAR_MasterTID: return 0; case ACS_THINGVAR_TargetTID: return thing->target ? thing->target->tid : 0; case ACS_THINGVAR_TracerTID: return thing->tracer ? thing->tracer->tid : 0; case ACS_THINGVAR_WaterLevel: return 0; case ACS_THINGVAR_ScaleX: return M_FloatToFixed(thing->xscale); case ACS_THINGVAR_ScaleY: return M_FloatToFixed(thing->yscale); case ACS_THINGVAR_Dormant: return !!(thing->flags2 & MF2_DORMANT); case ACS_THINGVAR_Mass: return thing->info->mass; case ACS_THINGVAR_Accuracy: return 0; case ACS_THINGVAR_Stamina: return 0; case ACS_THINGVAR_Height: return thing->height; case ACS_THINGVAR_Radius: return thing->radius; case ACS_THINGVAR_ReactionTime: return thing->reactiontime; case ACS_THINGVAR_MeleeRange: return MELEERANGE; case ACS_THINGVAR_ViewHeight: return 0; case ACS_THINGVAR_AttackZOff: return 0; case ACS_THINGVAR_StencilColor: return 0; case ACS_THINGVAR_Friction: return 0; case ACS_THINGVAR_DamageMult: return 0; case ACS_THINGVAR_Angle: return thing->angle >> 16; case ACS_THINGVAR_Armor: return thing->player ? thing->player->armorpoints : 0; case ACS_THINGVAR_CeilingTexture: return 0; case ACS_THINGVAR_CeilingZ: return thing->ceilingz; case ACS_THINGVAR_FloorTexture: return 0; case ACS_THINGVAR_FloorZ: return thing->floorz; case ACS_THINGVAR_Frags: return thing->player ? thing->player->totalfrags : 0; case ACS_THINGVAR_LightLevel: return thing->subsector->sector->lightlevel; case ACS_THINGVAR_MomX: return thing->momx; case ACS_THINGVAR_MomY: return thing->momy; case ACS_THINGVAR_MomZ: return thing->momz; case ACS_THINGVAR_Pitch: return thing->player ? thing->player->pitch >> 16 : 0; case ACS_THINGVAR_PlayerNumber: return thing->player ? thing->player - players : -1; case ACS_THINGVAR_SigilPieces: return 0; case ACS_THINGVAR_TID: return thing->tid; case ACS_THINGVAR_Type: return ACSVM::AddString(thing->info->name); case ACS_THINGVAR_X: return thing->x; case ACS_THINGVAR_Y: return thing->y; case ACS_THINGVAR_Z: return thing->z; default: return 0; } }
// // R_divideSegs // // Split the input list of segs into left and right lists using one of the segs // selected as a partition line for the current node. // static void R_divideSegs(rpolynode_t *rpn, dseglist_t *ts, dseglist_t *rs, dseglist_t *ls) { dynaseg_t *best, *add_to_rs = NULL, *add_to_ls = NULL; // select best seg to use as partition line best = rpn->partition = R_selectPartition(*ts); best->bsplink.remove(); #ifdef RANGECHECK // Should not happen. if(!rpn->partition) I_Error("R_divideSegs: could not select partition!\n"); #endif // use the partition line to split any other lines in the list that intersect // it into left and right halves double pdx = best->psx - best->pex; double pdy = best->psy - best->pey; dseglink_t *cur; // iterate from beginning until the original list is empty while((cur = *ts)) { dynaseg_t *seg = *cur; add_to_ls = add_to_rs = NULL; int val = R_classifyDynaSeg(best, seg, pdx, pdy); if(val == SPLIT_SR_EL || val == SPLIT_SL_ER) { double x, y; v2float_t fbackup; // seg is split by the partition R_ComputeIntersection(best, seg, x, y, &fbackup); // create a new vertex at the intersection point dynavertex_t *nv = R_GetFreeDynaVertex(); nv->fx = static_cast<float>(x); nv->fy = static_cast<float>(y); nv->fbackup = fbackup; nv->x = M_DoubleToFixed(x); nv->y = M_DoubleToFixed(y); nv->backup.x = M_FloatToFixed(nv->fbackup.x); nv->backup.y = M_FloatToFixed(nv->fbackup.y); // create a new dynaseg from nv to v2 dynaseg_t *nds = R_CreateDynaSeg(seg, nv, seg->seg.dyv2); R_setupDSForBSP(*nds); nds->seg.frontsector = seg->seg.frontsector; nds->seg.backsector = seg->seg.backsector; nds->seg.len = static_cast<float>(nds->len); // modify original seg to run from v1 to nv bool notmarked = !seg->originalv2; if(notmarked) // only if not already marked! R_SetDynaVertexRef(&seg->originalv2, seg->seg.dyv2); R_SetDynaVertexRef(&seg->seg.dyv2, nv); R_setupDSForBSP(*seg); seg->seg.len = static_cast<float>(seg->len); // add the new seg to the current node's ownership list, // so it can get freed later nds->ownerlink.insert(nds, &rpn->owned); if(notmarked) seg->alterlink.insert(seg, &rpn->altered); // classify left or right if(val == SPLIT_SR_EL) { add_to_ls = nds; add_to_rs = seg; } else { add_to_ls = seg; add_to_rs = nds; } } else { // Not split; which side? if(val & CLASSIFY_LEFT) add_to_ls = seg; // at least one vertex is left, other is left or on if(val & CLASSIFY_RIGHT) add_to_rs = seg; // at least one vertex is right, other is right or on if(val == CLASSIFY_ON) { // We know the segs are parallel or nearly so; take their dot // product to determine their relative orientation if((seg->psx - seg->pex) * pdx + (seg->psy - seg->pey) * pdy < 0.0) add_to_ls = seg; else add_to_rs = seg; } } // add to right side? if(add_to_rs) { add_to_rs->bsplink.remove(); add_to_rs->bsplink.insert(add_to_rs, rs); } // add to left side? if(add_to_ls) { add_to_ls->bsplink.remove(); add_to_ls->bsplink.insert(add_to_ls, ls); } } }