INT16 CMine::FindTriggerWall (INT16 trignum) { CDWall *wall = Walls (); int wallnum; for (wallnum = GameInfo ().walls.count; wallnum; wallnum--, wall++) if (wall->trigger == trignum) return wall - Walls (); return GameInfo ().walls.count; }
void CMine::CalcAverageCornerLight (bool bAll) { int segnum,pt,i,vertnum,count,sidenum,uvnum; UINT16 max_brightness; // smooth corner light by averaging all corners which share a vertex theApp.SetModified (TRUE); for (vertnum = 0; vertnum < VertCount (); vertnum++) { if (bAll || (*VertStatus (vertnum) & MARKED_MASK)) { max_brightness = 0; count = 0; // find all Segments () which share this point CDSegment *seg = Segments (); for (segnum = 0; segnum < SegCount (); segnum++, seg++) { for (pt = 0; pt < 8; pt++) { if (seg->verts[pt] == vertnum) { // add all the uvls for this point for (i = 0; i < 3; i++) { sidenum = point_sides[pt][i]; uvnum = point_corners[pt][i]; if ((seg->children[sidenum] < 0) || (seg->sides[sidenum].nWall < GameInfo ().walls.count)) { max_brightness = max(max_brightness,(UINT16)seg->sides[sidenum].uvls[uvnum].l); count++; } } } } } // now go back and set these light values if (count > 0) { theApp.SetModified (TRUE); // max_brightness = min(max_brightness,0x8000L); CDSegment *seg = Segments (); for (segnum=0;segnum<SegCount ();segnum++, seg++) { for (pt=0;pt<8;pt++) { if (seg->verts[pt] == vertnum) { for (i=0;i<3;i++) { sidenum = point_sides[pt][i]; uvnum = point_corners[pt][i]; if ((seg->children[sidenum] < 0) || (seg->sides[sidenum].nWall < GameInfo ().walls.count)) { seg->sides[sidenum].uvls[uvnum].l = max_brightness; } } } } } } } } }
INT16 CMine::FindTriggerWall (INT16 *trignum, INT16 segnum, INT16 sidenum) { GetCurrent (segnum, sidenum); CDWall *wall = Walls (); int wallnum; for (wallnum = GameInfo ().walls.count; wallnum; wallnum--, wall++) { if ((wall->segnum == segnum) && (wall->sidenum == sidenum)) { *trignum = wall->trigger; return wall - Walls (); } } *trignum = NO_TRIGGER; return GameInfo ().walls.count; }
void CMine::SetSegmentChildNum (CDSegment *pRoot, INT16 segnum,INT16 recursion_level) { INT16 sidenum, child, nImprove = 0; UINT16 nWall; CDSegment *seg = Segments () + segnum; CDSegment *prevSeg = NULL; bool bMarkChildren = false; // mark each child if child number is lower for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { // Skip if this is a door nWall = seg->sides [sidenum].nWall; // .. if there is a wall and its a door if ((nWall < GameInfo ().walls.count) && (Walls (nWall)->type == WALL_DOOR)) continue; // mark segment if it has a child child = seg->children [sidenum]; if ((child > -1) && (child < SegCount ()) && (recursion_level > seg->seg_number)) { if (seg->seg_number >= 0) ++nImprove; /* if (pRoot) { UnlinkSeg (seg, pRoot); LinkSeg (seg, pRoot); } */ seg->seg_number = recursion_level; bMarkChildren = true; break; } } //return if segment has no children or max recursion depth is reached if (!bMarkChildren || (recursion_level == 1)) return; // check each side of this segment for more children for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { // skip if there is a wall and its a door nWall = seg->sides [sidenum].nWall; if ((nWall < GameInfo ().walls.count) && (Walls (nWall)->type == WALL_DOOR)) continue; // check child child = seg->children [sidenum]; if ((child > -1) && (child < SegCount ())) SetSegmentChildNum (pRoot, child, recursion_level - 1); } }
int CMine::FindDeltaLight (INT16 segnum, INT16 sidenum, INT16 *pi) { int i = pi ? *pi : 0; int j = (int)GameInfo ().dl_indices.count++; dl_index *pdli = DLIndex (); if ((level_version >= 15) && (GameInfo ().fileinfo_version >= 34)) { for (; i < j; i++, pdli++) if ((pdli->d2x.segnum == segnum) && (pdli->d2x.sidenum = (UINT8) sidenum)) return i; } else { for (; i < j; i++, pdli++) if ((pdli->d2.segnum == segnum) && (pdli->d2.sidenum = (UINT8) sidenum)) return i; } return -1; }
INT16 CMine::FindTriggerTarget (INT16 trignum, INT16 segnum, INT16 sidenum) { CDTrigger *trigger = Triggers (); int i, j; for (i = trignum; i < GameInfo ().triggers.count; i++, trigger++) for (j = 0; j < trigger->num_links; j++) if ((trigger->seg [j] == segnum) && (trigger->side [j] == sidenum)) return i; return -1; }
void CMine::DeleteTrigger (INT16 nTrigger) { INT16 i, nSegment, nSide, nWall; if (nTrigger < 0) { nWall = CurrSeg ()->sides [Current ()->side].nWall; if (nWall >= GameInfo ().walls.count) return; nTrigger = Walls (nWall)->trigger; } if (nTrigger >= GameInfo ().triggers.count) return; // update all Walls () who point to Triggers () higher than this one // and unlink all Walls () who point to deleted trigger (should be only one wall) theApp.SetModified (TRUE); theApp.LockUndo (); CDWall *wallP = Walls (); for (i = GameInfo ().walls.count; i; i--, wallP++) if ((wallP->trigger != NO_TRIGGER) && (wallP->trigger > nTrigger)) wallP->trigger--; else if (wallP->trigger == nTrigger) { wallP->trigger = NO_TRIGGER; nSegment = wallP->segnum; nSide = wallP->sidenum; } // remove trigger from array //for (i=nTrigger;i<GameInfo ().triggers.count-1;i++) // update number of Triggers () CDTrigger *trigP = Triggers (); for (i = NumTriggers (); i; i--, trigP++) if (trigP->type >= TT_MASTER) DeleteTriggerTarget (trigP, nSegment, nSide, false); if (nTrigger < --GameInfo ().triggers.count) memcpy(Triggers (nTrigger), Triggers (nTrigger + 1), (GameInfo ().triggers.count - nTrigger) * sizeof(CDTrigger)); theApp.UnlockUndo (); theApp.MineView ()->Refresh (); AutoLinkExitToReactor(); }
void CMine::DeleteTriggerTargets (INT16 segnum, INT16 sidenum) { int i; for (i = 0; i < GameInfo ().triggers.count; i++) if (DeleteTriggerTarget (Triggers (i), segnum, sidenum)) i--; for (i = 0; i < NumObjTriggers (); i++) if (DeleteTriggerTarget (ObjTriggers (i), segnum, sidenum, false)) { DeleteObjTrigger (i); i--; } }
// // Action - Updates control center Triggers () so that exit door opens // when the reactor blows up. Removes any invalid cube/sides // from control_center_triggers if they exist. //------------------------------------------------------------------------ void auto_link_exit_to_reactor() { INT16 linknum,control,num_links,segnum,sidenum; UINT16 wallnum; UINT8 trignum; bool found; control = 0; // only 0 used by the game Descent // remove items from list that do not point to a wall for (linknum=0;linknum<control_center_triggers[control].num_links;linknum++) { num_links = control_center_triggers[control].num_links; segnum = control_center_triggers[control].seg[linknum]; sidenum = control_center_triggers[control].side[linknum]; // search for Walls () that have a exit of type trigger found = FALSE; for (wallnum=0;wallnum<GameInfo ().walls_howmany;wallnum++) { if (Walls (wallnum)->segnum == segnum && Walls ()[wallnum].sidenum == sidenum) { found = TRUE; break; } } // trignum = Walls (wallnum)->trigger; // if (trignum >= 0 && trignum <GameInfo ().triggers_howmany) { // if (Triggers ()[trignum].flags & (TRIGGER_EXIT | TRIGGER_SECRET_EXIT)) { // found = TRUE; // break; // } // } // } // } if (!found) { if (num_links > 0) { // just in case // move last link into this deleted link's spot control_center_triggers[control].seg [linknum] = control_center_triggers[control].seg[num_links-1]; control_center_triggers[control].side[linknum] = control_center_triggers[control].side[num_links-1]; control_center_triggers[control].seg [num_links-1] = 0; control_center_triggers[control].side[num_links-1] = 0; control_center_triggers[control].num_links--; } } } // add exit to list if not already in list // search for walls that have a exit of type trigger num_links = control_center_triggers[control].num_links; for (wallnum=0;wallnum<GameInfo ().walls_howmany;wallnum++) { trignum = Walls (wallnum)->trigger; if (trignum >= 0 && trignum <GameInfo ().triggers_howmany) { if ( file_type == RDL_FILE && Triggers ()[trignum].flags & (TRIGGER_EXIT | TRIGGER_SECRET_EXIT) || file_type != RDL_FILE && (Triggers ()[trignum].type == TT_EXIT || Triggers ()[trignum].type == TT_SECRET_EXIT) ) { // see if cube,side is already on the list segnum = (INT16)Walls (wallnum)->segnum; sidenum =(INT16)Walls (wallnum)->sidenum; found = FALSE; for (linknum=0;linknum<num_links;linknum++) { if (segnum == control_center_triggers[control].seg[linknum] && sidenum == control_center_triggers[control].side[linknum]) { found = TRUE; break; } } // if not already on the list, add it if (!found) { linknum = control_center_triggers[control].num_links; control_center_triggers[control].seg[linknum] = segnum; control_center_triggers[control].side[linknum] = sidenum; control_center_triggers[control].num_links++; } } } } }
void CGameSpy_Browser::ReadServerInfo (ServerInfo* pServerInfo, void* pServer) { CStringTable st; if (!pServer || !pServerInfo) return; sprintf_s(pServerInfo->m_Address, "%s:%d", xrGS_SBServerGetPublicAddress(pServer), xrGS_SBServerGetPublicQueryPort(pServer)); sprintf_s(pServerInfo->m_HostName, "%s", xrGS_SBServerGetPublicAddress(pServer)); sprintf_s(pServerInfo->m_ServerName, "%s", xrGS_SBServerGetStringValue(pServer, m_pQR2->xrGS_RegisteredKey(HOSTNAME_KEY), pServerInfo->m_HostName)); sprintf_s(pServerInfo->m_SessionName, "%s", xrGS_SBServerGetStringValue(pServer, m_pQR2->xrGS_RegisteredKey(MAPNAME_KEY), "Unknown")); sprintf_s(pServerInfo->m_ServerGameType, "%s", xrGS_SBServerGetStringValue(pServer, m_pQR2->xrGS_RegisteredKey(GAMETYPE_KEY), "Unknown")); pServerInfo->m_bPassword = xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(PASSWORD_KEY), SBFalse) == SBTrue; pServerInfo->m_bUserPass = xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(G_USER_PASSWORD_KEY), SBFalse) == SBTrue; #ifdef BATTLEYE pServerInfo->m_bBattlEye = xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(G_BATTLEYE_KEY), SBFalse) == SBTrue; #endif // BATTLEYE pServerInfo->m_Ping = (s16)(xrGS_SBServerGetPing(pServer) & 0xffff); pServerInfo->m_ServerNumPlayers = (s16)xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(NUMPLAYERS_KEY), 0); pServerInfo->m_ServerMaxPlayers = (s16)xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(MAXPLAYERS_KEY), 32); pServerInfo->m_ServerNumTeams = (s16)xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(NUMTEAMS_KEY), 0); pServerInfo->m_Port = (s16)xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(HOSTPORT_KEY), 0); pServerInfo->m_HPort = (s16)xrGS_SBServerGetPublicQueryPort(pServer); pServerInfo->m_bDedicated = (xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(DEDICATED_KEY), SBFalse)) == SBTrue; pServerInfo->m_GameType = (u8)xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(GAMETYPE_NAME_KEY), 0); if (pServerInfo->m_GameType == 0) { if (!xr_strcmp(pServerInfo->m_ServerGameType, "deathmatch")) pServerInfo->m_GameType = GAME_DEATHMATCH; else if (!xr_strcmp(pServerInfo->m_ServerGameType, "teamdeathmatch")) pServerInfo->m_GameType = GAME_TEAMDEATHMATCH; else if (!xr_strcmp(pServerInfo->m_ServerGameType, "artefacthunt")) pServerInfo->m_GameType = GAME_ARTEFACTHUNT; } sprintf_s(pServerInfo->m_ServerVersion, "%s", xrGS_SBServerGetStringValue(pServer, m_pQR2->xrGS_RegisteredKey(GAMEVER_KEY), "--")); //--------- Read Game Infos ---------------------------// pServerInfo->m_aInfos.clear(); pServerInfo->m_aPlayers.clear(); pServerInfo->m_aTeams.clear(); //-------------------------------------------------------// if (xrGS_SBServerHasFullKeys(pServer) == SBFalse) return; // pServerInfo->m_aInfos.push_back(GameInfo("Version:", pServerInfo->m_ServerVersion)); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_servername"), pServerInfo->m_ServerName)); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_version"), pServerInfo->m_ServerVersion)); #ifdef BATTLEYE ADD_BOOL_INFO(pServerInfo, pServer, "BattlEye", G_BATTLEYE_KEY); #endif // BATTLEYE ADD_INT_INFO_N (pServerInfo, pServer, 1, "Max ping", "", G_MAX_PING_KEY); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_maprotation"), G_MAP_ROTATION_KEY); pServerInfo->m_aInfos.push_back( GameInfo(*st.translate("mp_si_voting"), (xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(G_VOTING_ENABLED_KEY), SBFalse) == SBTrue) ? *st.translate("mp_si_enabled") : *st.translate("mp_si_disabled"))); // ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_voting"), G_VOTING_ENABLED_KEY); //----------------------------------------------------------------------- pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_spectatormodes"), "")); int SpectrModes = xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(G_SPECTATOR_MODES_KEY), 0); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_free_fly"), ((SpectrModes & (1<<CSpectator::eacFreeFly )) != 0) ? *st.translate("mp_si_yes") : *st.translate("mp_si_no"))); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_first_eye"), ((SpectrModes & (1<<CSpectator::eacFirstEye )) != 0) ? *st.translate("mp_si_yes") : *st.translate("mp_si_no"))); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_look_at"), ((SpectrModes & (1<<CSpectator::eacLookAt )) != 0) ? *st.translate("mp_si_yes") : *st.translate("mp_si_no"))); pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_free_look"), ((SpectrModes & (1<<CSpectator::eacFreeLook )) != 0) ? *st.translate("mp_si_yes") : *st.translate("mp_si_no"))); if (pServerInfo->m_GameType != GAME_DEATHMATCH) pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_team_only"), ((SpectrModes & (1<<CSpectator::eacMaxCam )) != 0) ? *st.translate("mp_si_yes") : *st.translate("mp_si_no"))); //----------------------------------------------------------------------- if (pServerInfo->m_GameType == GAME_DEATHMATCH || pServerInfo->m_GameType == GAME_TEAMDEATHMATCH) { ADD_INT_INFO_N (pServerInfo, pServer, 1, *st.translate("mp_si_fraglimit"), "", G_FRAG_LIMIT_KEY); } ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_time_limit"), "%.0f %s",*st.translate("mp_si_min"), G_TIME_LIMIT_KEY); if (xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(G_DAMAGE_BLOCK_TIME_KEY), 0) != 0) { pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_invinsibility"), "")); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_invinsibility_indicators"), G_DAMAGE_BLOCK_INDICATOR_KEY); ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_invinsibility_time"), "%.f %s",*st.translate("mp_si_sec"), G_DAMAGE_BLOCK_TIME_KEY); } ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_anomalies"), G_ANOMALIES_ENABLED_KEY); if ((xrGS_SBServerGetBoolValue(pServer, m_pQR2->xrGS_RegisteredKey(G_ANOMALIES_ENABLED_KEY), SBFalse)) == SBTrue) { if (xrGS_SBServerGetIntValue(pServer, m_pQR2->xrGS_RegisteredKey(G_ANOMALIES_TIME_KEY),0) != 0) { ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_anomalies_period"), "%.1f %s",*st.translate("mp_si_min"), G_ANOMALIES_TIME_KEY); } else pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_anomalies_period"), *st.translate("mp_si_infinite"))); } ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_forcerespawn"), "%.f %s",*st.translate("mp_si_sec"), G_FORCE_RESPAWN_KEY); ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_warmuptime"), "%.0f %s",*st.translate("mp_si_sec"), G_WARM_UP_TIME_KEY); if (pServerInfo->m_GameType == GAME_TEAMDEATHMATCH || pServerInfo->m_GameType == GAME_ARTEFACTHUNT) { ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_autoteam_balance"), G_AUTO_TEAM_BALANCE_KEY); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_autoteam_swap"), G_AUTO_TEAM_SWAP_KEY); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_friendly_indicators"), G_FRIENDLY_INDICATORS_KEY); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_friendly_names"), G_FRIENDLY_NAMES_KEY); ADD_INT_INFO_N (pServerInfo, pServer, 1/100.0f, *st.translate("mp_si_friendly_fire"), " %%", G_FRIENDLY_FIRE_KEY); }; if (pServerInfo->m_GameType == GAME_ARTEFACTHUNT) { pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_artefacts"), "")); ADD_INT_INFO(pServerInfo, pServer, *st.translate("mp_si_afcount"), G_ARTEFACTS_COUNT_KEY ); ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_afstaytime"), "%.2f %s",*st.translate("mp_si_min"), G_ARTEFACT_STAY_TIME_KEY); ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_afrespawntime"), "%.0f %s",*st.translate("mp_si_sec"), G_ARTEFACT_RESPAWN_TIME_KEY); int Reinforcement = atoi(xrGS_SBServerGetStringValue(pServer, m_pQR2->xrGS_RegisteredKey(G_REINFORCEMENT_KEY), "0")); switch (Reinforcement) { case -1: pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_players_respawn"), *st.translate("mp_si_artefact_captured"))); break; case 0: pServerInfo->m_aInfos.push_back(GameInfo(*st.translate("mp_si_players_respawn"), *st.translate("mp_si_any_time"))); break; default: ADD_TIME_INFO(pServerInfo, pServer, 1.0f, *st.translate("mp_si_players_respawn"), "%.0f %s",*st.translate("mp_si_sec"), G_REINFORCEMENT_KEY); break; } ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_shielded_bases"), G_SHIELDED_BASES_KEY ); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_return_players"), G_RETURN_PLAYERS_KEY ); ADD_BOOL_INFO(pServerInfo, pServer, *st.translate("mp_si_afbearer_cant_sprint"), G_BEARER_CANT_SPRINT_KEY); } //--------- Read Players Info -------------------------// for (int i=0; i<pServerInfo->m_ServerNumPlayers; i++) { PlayerInfo PInfo; sprintf_s(PInfo.Name, "%s", xrGS_SBServerGetPlayerStringValue(pServer, i, "player", "Unknown")); PInfo.Frags = s16(xrGS_SBServerGetPlayerIntValue(pServer, i, "score", 0)); PInfo.Deaths = u16(xrGS_SBServerGetPlayerIntValue(pServer, i, "deaths", 0)); PInfo.Rank = u8(xrGS_SBServerGetPlayerIntValue(pServer, i, "skill", 0)); PInfo.Team = u8(xrGS_SBServerGetPlayerIntValue(pServer, i, "team", 0)); PInfo.Spectator = (xrGS_SBServerGetPlayerIntValue(pServer, i, "spectator", 1)) != 0; PInfo.Artefacts = u8(xrGS_SBServerGetPlayerIntValue(pServer, i, "artefacts", 0)); pServerInfo->m_aPlayers.push_back(PInfo); }; //----------- Read Team Info ---------------------------// if (pServerInfo->m_GameType == GAME_TEAMDEATHMATCH || pServerInfo->m_GameType == GAME_ARTEFACTHUNT) { for (int i=0; i<pServerInfo->m_ServerNumTeams; i++) { TeamInfo TI; TI.Score = u8(xrGS_SBServerGetTeamIntValue(pServer, i, "t_score", 0)); pServerInfo->m_aTeams.push_back(TI); } } };
bool CMine::CalcDeltaLights (double fLightScale, int force, int recursion_depth) { // initialize totals CDSegment *srcseg, *childseg; int source_segnum, child_segnum; double effect[4]; GameInfo ().delta_lights.count = 0; GameInfo ().dl_indices.count = 0; bool bWall, bD2XLights = (level_version >= 15) && (GameInfo ().fileinfo_version >= 34); fLightScale = 1.0; ///= 100.0; for (source_segnum = 0, srcseg = Segments (); source_segnum < SegCount (); source_segnum++, srcseg++) { // skip if not marked unless we are automatically saving if (!(srcseg->wall_bitmask & MARKED_MASK) && !force) continue; // loop on all sides int source_sidenum; for (source_sidenum = 0; source_sidenum < 6; source_sidenum++) { INT16 tmapnum = srcseg->sides [source_sidenum].nBaseTex & 0x3fff; INT16 tmapnum2 = srcseg->sides [source_sidenum].nOvlTex & 0x3fff; INT16 trignum; bool bl1 = (bool) (IsLight (tmapnum) != -1); bool bl2 = (bool) (IsLight (tmapnum2) != -1); if (!(bl1 || bl2)) continue; // no lights on this side bool bCalcDeltas = false; // if the current side is a wall and has a light and is the target of a trigger // than can make the wall appear/disappear, calculate delta lights for it if ((bWall = (FindWall (source_segnum, source_sidenum) != NULL)) && ((trignum = FindTriggerTarget (0, source_segnum, source_sidenum)) >= 0)) { INT8 trigtype = Triggers (trignum)->type; bCalcDeltas = (trigtype == TT_ILLUSION_OFF) || (trigtype == TT_ILLUSION_ON) || (trigtype == TT_CLOSE_WALL) || (trigtype == TT_OPEN_WALL) || (trigtype == TT_LIGHT_OFF) || (trigtype == TT_LIGHT_ON); } if (!bCalcDeltas) bCalcDeltas = IsFlickeringLight (source_segnum, source_sidenum); if (!bCalcDeltas) { bool bb1 = IsBlastableLight (tmapnum); bool bb2 = IsBlastableLight (tmapnum2); if (bb1 == bb2) bCalcDeltas = bb1; // both lights blastable or not else if (!(bb1 ? bl2 : bl1)) // i.e. one light blastable and the other texture not a non-blastable light bCalcDeltas = true; } if (!bCalcDeltas) { //check if light is target of a "light on/off" trigger int trignum = FindTriggerTarget (0, source_segnum, source_sidenum); if ((trignum >= 0) && (Triggers (trignum)->type >= TT_LIGHT_OFF)) bCalcDeltas = true; } if (!bCalcDeltas) continue; // only set lights for textures which have a nOvlTex //if (tmapnum2 == 0) // continue; INT16 srcwall = srcseg->sides [source_sidenum].nWall; if ((srcseg->children [source_sidenum] != -1) && ((srcwall >= GameInfo ().walls.count) || (Walls (srcwall)->type == WALL_OPEN))) continue; // if ((IsLight (tmapnum) == -1) && (IsLight (tmapnum2) == -1)) // continue; if (GameInfo ().dl_indices.count >= MAX_DL_INDICES) { char szMsg [256]; sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth); DEBUGMSG (szMsg); return false; } vms_vector A,source_center; // get index number and increment total number of dl_indices int dl_index_num = (int)GameInfo ().dl_indices.count++; dl_index *pdli = DLIndex (dl_index_num); if (bD2XLights) { pdli->d2x.segnum = source_segnum; pdli->d2x.sidenum = source_sidenum; pdli->d2x.count = 0; // will be incremented below } else { pdli->d2.segnum = source_segnum; pdli->d2.sidenum = source_sidenum; pdli->d2.count = 0; // will be incremented below } pdli->d2.index = (INT16)GameInfo ().delta_lights.count; // find orthogonal angle of source segment CalcOrthoVector(A,source_segnum,source_sidenum); // remember to flip the sign since we want it to point inward A.x = -A.x; A.y = -A.y; A.z = -A.z; // calculate the center of the source segment CalcCenter(source_center,source_segnum,source_sidenum); // mark those Segments () within N children of current cube //(note: this is done once per light instead of once per segment // even though some Segments () have multiple lights. // This actually reduces the number of calls since most // Segments () do not have lights) int h; for (h = 0; h < SegCount (); h++) Segments (h)->seg_number = -1; SetSegmentChildNum (srcseg, source_segnum, recursion_depth); srcseg->seg_number = recursion_depth; // setup source corner vertex for length calculation later vms_vector source_corner[4]; int j; for (j = 0; j < 4; j++) { UINT8 vertnum = side_vert[source_sidenum][j]; int h = srcseg->verts[vertnum]; source_corner[j].x = Vertices (h)->x; source_corner[j].y = Vertices (h)->y; source_corner[j].z = Vertices (h)->z; } // loop on child Segments () for (child_segnum = 0, childseg = Segments (); child_segnum < SegCount (); child_segnum++, childseg++) { if (childseg->seg_number < 0) continue; // loop on child sides int child_sidenum; for (child_sidenum = 0; child_sidenum < 6; child_sidenum++) { // if texture has a child.. #ifdef _DEBUG CBRK (source_segnum == 6 && source_sidenum == 2 && child_segnum == 10 && child_sidenum == 1); #endif if (childseg->children[child_sidenum] >= 0) { UINT16 nWall = childseg->sides[child_sidenum].nWall; // .. if there is no wall .. if (nWall >= GameInfo ().walls.count) continue; // .. or its not a door .. if (Walls (nWall)->type == WALL_OPEN) continue; // don't put light because there is no texture here } // don't affect non-flickering light emitting textures (e.g. lava) tmapnum = childseg->sides [child_sidenum].nBaseTex; tmapnum2 = childseg->sides [child_sidenum].nOvlTex & 0x3fff; if (m_nNoLightDeltas == 1) { if (((IsLight (tmapnum) >= 0) || (IsLight (tmapnum2) >= 0)) && !IsFlickeringLight (child_segnum, child_sidenum)) continue; } else if ((m_nNoLightDeltas == 2) && (IsLava (tmapnum) || IsLava (tmapnum2))) continue; // if the child side is the same as the source side, then set light and continue if (child_sidenum == source_sidenum && child_segnum == source_segnum) { if ((GameInfo ().delta_lights.count >= MAX_DELTA_LIGHTS) || (bD2XLights ? pdli->d2x.count == 8191 : pdli->d2.count == 255)) { char szMsg [256]; sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth); DEBUGMSG (szMsg); return false; } delta_light *dl = DeltaLights (GameInfo ().delta_lights.count++); dl->segnum = child_segnum; dl->sidenum = child_sidenum; dl->dummy = 0; dl->vert_light [0] = dl->vert_light [1] = dl->vert_light [2] = dl->vert_light [3] = (UINT8) min (32, 32 * fLightScale); if (bD2XLights) pdli->d2x.count++; else pdli->d2.count++; continue; } // calculate vector between center of source segment and center of child #ifdef _DEBUG CBRK (child_segnum == qqq1 && child_sidenum == qqq2); #endif if (CalcSideLights (child_segnum, child_sidenum, source_center, source_corner, A, effect, fLightScale, bWall)) { theApp.SetModified (TRUE); if ((GameInfo ().delta_lights.count >= MAX_DELTA_LIGHTS) || (bD2XLights ? pdli->d2x.count == 8191 : pdli->d2.count == 255)) { char szMsg [256]; sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth); DEBUGMSG (szMsg); return false; } delta_light *dl = DeltaLights (GameInfo ().delta_lights.count++); dl->segnum = child_segnum; dl->sidenum = child_sidenum; dl->dummy = 0; int iCorner; for (iCorner = 0; iCorner < 4; iCorner++) dl->vert_light [iCorner] = (UINT8) min(32, effect [iCorner]); if (bD2XLights) pdli->d2x.count++; else pdli->d2.count++; } } } // } } } return true; }
void CMine::Illuminate ( INT16 source_segnum, INT16 source_sidenum, UINT32 brightness, double fLightScale, bool bAll, bool bCopyTexLights) { CDSegment *seg = Segments (); CDSegment *child_seg; double effect[4]; // find orthogonal angle of source segment vms_vector A; //fLightScale /= 100.0; CalcOrthoVector (A,source_segnum,source_sidenum); // remember to flip the sign since we want it to point inward A.x = -A.x; A.y = -A.y; A.z = -A.z; // calculate the center of the source segment vms_vector source_center; CalcCenter (source_center,source_segnum,source_sidenum); if ((source_segnum == 911) && (source_sidenum == 3)) A = A; // mark those Segments () within N children of current cube // set child numbers //Segments ()[source_segnum].seg_number = m_lightRenderDepth; int i; for (i = SegCount (); i; i--, seg++) seg->seg_number = -1; SetSegmentChildNum (NULL, source_segnum, m_lightRenderDepth); CDColor *plc = LightColor (source_segnum, source_sidenum); if (!plc->index) { plc->index = 255; plc->color.r = plc->color.g = plc->color.b = 1.0; } if (UseTexColors () && bCopyTexLights) { CDColor *psc = LightColor (source_segnum, source_sidenum, false); *psc = *plc; } seg = Segments (source_segnum); seg->seg_number = m_lightRenderDepth; bool bWall = false; //FindWall (source_segnum, source_sidenum) != NULL; // loop on child Segments () int child_segnum; for (child_segnum=0, child_seg = Segments ();child_segnum<SegCount ();child_segnum++, child_seg++) { // skip if this is not viewable if (child_seg->seg_number < 0) continue; // skip if not marked // if (!(bAll || (child_seg->wall_bitmask & MARKED_MASK))) // continue; // setup source corner vertex for length calculation later vms_vector source_corner[4]; int j; for (j = 0; j < 4; j++) { int vertnum = side_vert [source_sidenum][j]; int h = seg->verts [vertnum]; source_corner[j].x = Vertices (h)->x; source_corner[j].y = Vertices (h)->y; source_corner[j].z = Vertices (h)->z; } // loop on child sides int child_sidenum; for (child_sidenum = 0; child_sidenum < 6; child_sidenum++) { // if side has a child.. if (!(bAll || SideIsMarked (child_segnum, child_sidenum))) continue; if (child_seg->children[child_sidenum] >= 0) { UINT16 nWall = child_seg->sides[child_sidenum].nWall; // .. but there is no wall .. if (nWall >= GameInfo ().walls.count) continue; // .. or its not a door .. if (Walls (nWall)->type == WALL_OPEN) continue; } // CBRK (psc->index > 0); // if the child side is the same as the source side, then set light and continue #ifdef _DEBUG CBRK (child_segnum == qqq1 && child_sidenum == qqq2); #endif if (child_sidenum == source_sidenum && child_segnum == source_segnum) { uvl *uvlP = child_seg->sides [child_sidenum].uvls; UINT32 vBr, lBr; theApp.SetModified (TRUE); int j; for (j = 0; j < 4; j++, uvlP++) { CDColor *pvc = VertexColors (child_seg->verts [side_vert [child_sidenum][j]]); vBr = (UINT16) uvlP->l; lBr = (UINT32) (brightness * fLightScale); BlendColors (plc, pvc, lBr, vBr); vBr += lBr; vBr = min (0x8000, vBr); uvlP->l = (UINT16) vBr; } continue; } // calculate vector between center of source segment and center of child // CBRK (child_segnum == 1 && child_sidenum == 2); if (CalcSideLights (child_segnum, child_sidenum, source_center, source_corner, A, effect, fLightScale, bWall)) { UINT32 vBr, lBr; //vertex brightness, light brightness uvl *uvlP = child_seg->sides [child_sidenum].uvls; theApp.SetModified (TRUE); int j; for (j = 0; j < 4; j++, uvlP++) { CDColor *pvc = VertexColors (child_seg->verts [side_vert [child_sidenum][j]]); if (child_seg->verts [side_vert [child_sidenum][j]] == 2368) j = j; vBr = (UINT16) uvlP->l; lBr = (UINT16) (brightness * effect [j] / 32); BlendColors (plc, pvc, lBr, vBr); vBr += lBr; vBr = min (0x8000, vBr); uvlP->l = (UINT16) vBr; } } } } }
CDTrigger *CMine::AddTrigger (UINT16 wallnum, INT16 type, BOOL bAutoAddWall) { INT16 flags; INT16 segnum, sidenum, trignum; static INT16 defWallTypes [NUM_TRIGGER_TYPES] = { WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_ILLUSION, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_OPEN, WALL_ILLUSION, WALL_OPEN, WALL_OPEN }; static INT16 defWallTextures [NUM_TRIGGER_TYPES] = { 0, 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, 0 }; // check if there's already a trigger on the current side wallnum = FindTriggerWall (&trignum); if (trignum != NO_TRIGGER) { ErrorMsg ("There is already a trigger on this side"); return NULL; } if (GameInfo ().triggers.count >= MAX_TRIGGERS) { ErrorMsg ("The maximum number of triggers has been reached."); return NULL; } // if no wall at current side, try to add a wall of proper type bool bUndo = theApp.SetModified (TRUE); theApp.LockUndo (); if (CurrSide ()->nWall >= GameInfo ().walls.count) { if (bAutoAddWall) { if (GameInfo ().walls.count >= MAX_WALLS) { ErrorMsg ("Cannot add a wall to this side,\nsince the maximum number of walls is already reached."); return NULL; } segnum = sidenum = -1; GetCurrent (segnum, sidenum); if (!AddWall (-1, -1, (Segments (segnum)->children [sidenum] < 0) ? WALL_OVERLAY : defWallTypes [type], 0, 0, -1, defWallTextures [type])) { ErrorMsg ("Cannot add a wall for this trigger."); theApp.ResetModified (bUndo); return NULL; } } else { ErrorMsg ("You must add a wall to this side before you can add a trigger."); return NULL; } } // if D1, then convert type to flag value if (file_type == RDL_FILE) { switch(type) { case TT_OPEN_DOOR: flags = TRIGGER_CONTROL_DOORS; break; case TT_MATCEN: flags = TRIGGER_MATCEN; break; case TT_EXIT: flags = TRIGGER_EXIT; break; case TT_SECRET_EXIT: flags = TRIGGER_SECRET_EXIT; break; case TT_ILLUSION_OFF: flags = TRIGGER_ILLUSION_OFF; break; case TT_ILLUSION_ON: flags = TRIGGER_ILLUSION_ON; break; case TT_ENERGY_DRAIN: flags = TRIGGER_ENERGY_DRAIN; break; case TT_SHIELD_DAMAGE: flags = TRIGGER_SHIELD_DAMAGE; break; default: flags = 0; } type = 0; } else flags = 0; trignum = (UINT16) GameInfo ().triggers.count; // set new trigger data InitTrigger (Triggers (trignum), type, flags); // link trigger to the wall Walls (wallnum)->trigger = (UINT8) trignum; // update number of Triggers () GameInfo ().triggers.count++; AutoLinkExitToReactor(); theApp.UnlockUndo (); theApp.MineView ()->Refresh (); return Triggers (trignum); }
void CMine::AutoLinkExitToReactor () { INT16 linknum,control,num_links,segnum,sidenum; UINT16 wallnum; INT8 trignum; bool found; control = 0; // only 0 used by the game Descent control_center_trigger *ccTrigger = CCTriggers (control); theApp.SetModified (TRUE); theApp.LockUndo (); // remove items from list that do not point to a wall for (linknum = 0; linknum < ccTrigger->num_links; linknum++) { num_links = ccTrigger->num_links; segnum = ccTrigger->seg [linknum]; sidenum = ccTrigger->side [linknum]; // search for Walls () that have a exit of type trigger found = FALSE; for (wallnum=0;wallnum<GameInfo ().walls.count;wallnum++) { if (Walls (wallnum)->segnum == segnum && Walls (wallnum)->sidenum == sidenum) { found = TRUE; break; } } if (!found) { if (num_links > 0) { // just in case // move last link into this deleted link's spot ccTrigger->seg [linknum] = ccTrigger->seg [num_links-1]; ccTrigger->side [linknum] = ccTrigger->side [num_links-1]; ccTrigger->seg [num_links-1] = 0; ccTrigger->side [num_links-1] = 0; ccTrigger->num_links--; } } } // add exit to list if not already in list // search for Walls () that have a exit of type trigger num_links = ccTrigger->num_links; for (wallnum = 0; wallnum < GameInfo ().walls.count; wallnum++) { trignum = Walls (wallnum)->trigger; if (trignum >= 0 && trignum <GameInfo ().triggers.count) { if ((file_type == RDL_FILE) ? Triggers (trignum)->flags & (TRIGGER_EXIT | TRIGGER_SECRET_EXIT) : Triggers (trignum)->type == TT_EXIT || Triggers (trignum)->type == TT_SECRET_EXIT) { // see if cube,side is already on the list segnum = (INT16)Walls (wallnum)->segnum; sidenum =(INT16)Walls (wallnum)->sidenum; found = FALSE; for (linknum = 0; linknum < num_links; linknum++) { if (segnum == ccTrigger->seg [linknum] && sidenum == ccTrigger->side [linknum]) { found = TRUE; break; } } // if not already on the list, add it if (!found) { linknum = ccTrigger->num_links; ccTrigger->seg [linknum] = segnum; ccTrigger->side [linknum] = sidenum; ccTrigger->num_links++; } } } } theApp.UnlockUndo (); }
void CMine::SpinSelection(double angle) { int nSegment = Current ()->segment; int nSide = Current ()->side; CDSegment *seg = Segments (nSegment); CDObject *obj; vms_vector center,opp_center; INT16 i; #ifdef SPIN_RELATIVE double xspin,yspin,zspin; vms_vector rel [3]; #endif /* calculate segment pointer */ switch (m_selectMode) { case POINT_MODE: ErrorMsg ("Cannot spin a point"); break; /* can't spin a point */ case LINE_MODE: ErrorMsg ("Cannot spin a line"); break; /* line spinning not supported */ case SIDE_MODE: // spin side around its center in the plane of the side // calculate center of current side theApp.SetModified (TRUE); center.x = center.y = center.z = 0; for (i = 0; i < 4; i++) { center.x += Vertices (seg->verts [side_vert [nSide][i]])->x; center.y += Vertices (seg->verts [side_vert [nSide][i]])->y; center.z += Vertices (seg->verts [side_vert [nSide][i]])->z; } center.x /= 4; center.y /= 4; center.z /= 4; // calculate orthogonal vector from lines which intersect point 0 // |x y z | // AxB = |ax ay az| = x(aybz-azby), y(azbx-axbz), z(axby-aybx) // |bx by bz| struct vector {double x,y,z;}; struct vector a,b,c; double length; INT16 vertnum1,vertnum2; vertnum1 = seg->verts [side_vert [nSide][0]]; vertnum2 = seg->verts [side_vert [nSide][1]]; a.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x); a.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y); a.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z); vertnum1 = seg->verts [side_vert [nSide][0]]; vertnum2 = seg->verts [side_vert [nSide][3]]; b.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x); b.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y); b.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z); c.x = a.y*b.z - a.z*b.y; c.y = a.z*b.x - a.x*b.z; c.z = a.x*b.y - a.y*b.x; // normalize the vector length = sqrt(c.x*c.x + c.y*c.y + c.z*c.z); c.x /= length; c.y /= length; c.z /= length; // set sign (since vert numbers for most sides don't follow right-handed convention) if (nSide!=1 && nSide!=5) { c.x = -c.x; c.y = -c.y; c.z = -c.z; } // set opposite center opp_center.x = center.x + (FIX)(0x10000L*c.x); opp_center.y = center.y + (FIX)(0x10000L*c.y); opp_center.z = center.z + (FIX)(0x10000L*c.z); /* rotate points around a line */ for (i = 0; i < 4; i++) { RotateVertex(Vertices (seg->verts [side_vert [nSide][i]]), ¢er,&opp_center,angle); } break; case CUBE_MODE: // spin cube around the center of the cube using screen's perspective // calculate center of current cube theApp.SetModified (TRUE); center.x = center.y = center.z = 0; for (i = 0; i < 8; i++) { center.x += Vertices (seg->verts [i])->x; center.y += Vertices (seg->verts [i])->y; center.z += Vertices (seg->verts [i])->z; } center.x /= 8; center.y /= 8; center.z /= 8; // calculate center of oppisite current side opp_center.x = opp_center.y = opp_center.z = 0; for (i = 0; i < 4; i++) { opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x; opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y; opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z; } opp_center.x /= 4; opp_center.y /= 4; opp_center.z /= 4; // rotate points about a point for (i = 0; i < 8; i++) RotateVertex(Vertices (seg->verts [i]),¢er,&opp_center,angle); break; case OBJECT_MODE: // spin object vector theApp.SetModified (TRUE); vms_matrix *orient; orient = (Current ()->object == GameInfo ().objects.count) ? &SecretOrient () : &CurrObj ()->orient; switch (nSide) { case 0: RotateVmsMatrix(orient,angle,'x'); break; case 2: RotateVmsMatrix(orient,-angle,'x'); break; case 1: RotateVmsMatrix(orient,-angle,'y'); break; case 3: RotateVmsMatrix(orient,angle,'y'); break; case 4: RotateVmsMatrix(orient,angle,'z'); break; case 5: RotateVmsMatrix(orient,-angle,'z'); break; } #ifdef SPIN_RELATIVE // calculate angles to spin the side into the x-y plane // use points 0,1, and 2 of the side // make point0 the origin // and get coordinates of points 1 and 2 relative to point 0 for (i=0;i<3;i++) { rel [i].x = vertices [seg->verts [side_vert [nSide][i]]].x - vertices [seg->verts [side_vert [nSide][0]]].x; rel [i].y = vertices [seg->verts [side_vert [nSide][i]]].y - vertices [seg->verts [side_vert [nSide][0]]].y; rel [i].z = vertices [seg->verts [side_vert [nSide][i]]].z - vertices [seg->verts [side_vert [nSide][0]]].z; } // calculate z-axis spin angle to rotate point1 so it lies in x-y plane zspin = (rel [1].x==rel [1].y) ? PI/4 : atan2(rel [1].y,rel [1].x); // spin all 3 points on z axis for (i=0;i<3;i++) RotateVmsVector(&rel [i],zspin,'z'); // calculate y-axis spin angle to rotate point1 so it lies on x axis yspin = (rel [1].z==rel [1].x) ? PI/4 : atan2(rel [1].z,rel [1].x); // spin points 1 and 2 on y axis (don't need to spin point 0 since it is at 0,0,0) for (i=1;i<=2;i++) RotateVmsVector(&rel [i],yspin,'y'); // calculate x-axis spin angle to rotate point2 so it lies in x-y plane xspin = (rel [2].z==rel [2].y) ? PI/4 : atan2(rel [2].z,rel [2].y); // spin points 2 on x axis (don't need to spin point 1 since it is on the x-axis RotateVmsVector(&rel [2],xspin,'x'); RotateVmsMatrix(&obj->orient,zspin,'z'); RotateVmsMatrix(&obj->orient,yspin,'y'); RotateVmsMatrix(&obj->orient,xspin,'x'); RotateVmsMatrix(&obj->orient,-xspin,'x'); RotateVmsMatrix(&obj->orient,-yspin,'y'); RotateVmsMatrix(&obj->orient,-zspin,'z'); #endif //SPIN_RELATIVE break; case BLOCK_MODE: theApp.SetModified (TRUE); // calculate center of current cube center.x = center.y = center.z = 0; for (i = 0; i < 8; i++) { center.x += Vertices (seg->verts [i])->x; center.y += Vertices (seg->verts [i])->y; center.z += Vertices (seg->verts [i])->z; } center.x /= 8; center.y /= 8; center.z /= 8; // calculate center of oppisite current side opp_center.x = opp_center.y = opp_center.z = 0; for (i = 0; i < 4; i++) { opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x; opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y; opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z; } opp_center.x /= 4; opp_center.y /= 4; opp_center.z /= 4; // rotate points about a point for (i=0;i<VertCount ();i++) if (*VertStatus (i) & MARKED_MASK) RotateVertex(Vertices (i),¢er,&opp_center,angle); // rotate Objects () within marked cubes obj = Objects (); for (i = GameInfo ().objects.count; i; i--, obj++) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) RotateVertex(&obj->pos, ¢er, &opp_center, angle); break; } }
void CMine::MoveOn (char axis,INT32 inc) { int nSegment = Current ()->segment; int nSide = Current ()->side; int nPoint = Current ()->point; int nLine = Current ()->line; CDSegment *seg = Segments (nSegment); INT16 i; theApp.SetModified (TRUE); switch (m_selectMode) { case POINT_MODE: switch (axis) { case 'X': Vertices (seg->verts [side_vert [nSide][nPoint]])->x += inc; break; case 'Y': Vertices (seg->verts [side_vert [nSide][nPoint]])->y += inc; break; case 'Z': Vertices (seg->verts [side_vert [nSide][nPoint]])->z += inc; break; } break; case LINE_MODE: switch (axis) { case 'X': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->x += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->x += inc; break; case 'Y': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->y += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->y += inc; break; case 'Z': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->z += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->z += inc; break; } break; case SIDE_MODE: switch (axis) { case 'X': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->x += inc; break; case 'Y': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->y += inc; break; case 'Z': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->z += inc; break; } break; case CUBE_MODE: switch (axis) { case 'X': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->x += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.x += inc; break; case 'Y': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->y += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.y += inc; break; case 'Z': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->z += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.z += inc; break; } break; case OBJECT_MODE: switch (axis) { case 'X': CurrObj ()->pos.x += inc; break; case 'Y': CurrObj ()->pos.y += inc; break; case 'Z': CurrObj ()->pos.z += inc; break; } break; case BLOCK_MODE: CDObject *obj = Objects (); switch (axis) { case 'X': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->x += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.x += inc; break; case 'Y': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->y += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.y += inc; break; case 'Z': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->z += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.z += inc; break; } break; } }