// [RH] Check dmflags for noexit and respond accordingly bool CheckIfExitIsGood (AActor *self, level_info_t *info) { cluster_info_t *cluster; // The world can always exit itself. if (self == NULL) return true; // We must kill all monsters to exit the level. if ((dmflags2 & DF2_KILL_MONSTERS) && level.killed_monsters != level.total_monsters) return false; // Is this a deathmatch game and we're not allowed to exit? if ((deathmatch || alwaysapplydmflags) && (dmflags & DF_NO_EXIT)) { P_DamageMobj (self, self, self, TELEFRAG_DAMAGE, NAME_Exit); return false; } // Is this a singleplayer game and the next map is part of the same hub and we're dead? if (self->health <= 0 && !multiplayer && info != NULL && info->cluster == level.cluster && (cluster = FindClusterInfo(level.cluster)) != NULL && cluster->flags & CLUSTER_HUB) { return false; } if (deathmatch && gameaction != ga_completed) { Printf ("%s exited the level.\n", self->player->userinfo.GetName()); } return true; }
/* * Note also that the CountofClusters value is exactly that—the count of data * clusters starting at cluster * 2. The maximum valid cluster number for the volume is CountofClusters + 1, * and the “count of clusters including the two reserved clusters” is CountofClusters + 2. */ int SetRootDir(FILE * img) { struct cluster temp; fatcat.rootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytesPerSec - 1)) / BPB_BytesPerSec; fatcat.firstDataSector = BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATSz32) + fatcat.rootDirSectors; fatcat.dataSectors = BPB_TotSec32 -(BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATSz32) + fatcat.rootDirSectors); fatcat.dataClusters = fatcat.dataSectors / BPB_SecPerClus; if(fatcat.dataClusters < 65526) return -1; temp = FindClusterInfo(BPB_RootClus); memcpy(fatcat.curDir->cluster, &temp, sizeof(struct cluster)); fatcat.dirName = "/"; #ifdef _DEBUGGING_BOOT_SECT printf("\n\nRoot Directory Address: %d", fatcat.rootDirSectors); printf("\nFirst Data Sector: 0x%x", fatcat.firstDataSector); printf("\nTotal Data Sectors: %d", fatcat.dataSectors); printf("\nTotal Data Clusters: %d\n\n", fatcat.dataClusters); #endif return 0; }
struct cluster getfreeclus(FILE * img){ struct cluster free; fseek(img, BPB_FSInfo * BPB_BytesPerSec, SEEK_SET); fread(&fatcat.fsinfo.FSI_LeadSig, 4, 1, img); fseek(img, 480, SEEK_CUR); fread(&fatcat.fsinfo.FSI_StrcSig, 4, 1, img); if(fatcat.fsinfo.FSI_LeadSig == LEAD_SIG_VAL && fatcat.fsinfo.FSI_StrcSig == STRUC_SIG_VAL){ fread(&fatcat.fsinfo.FSI_Free_Count, 4, 1, img); fread(&fatcat.fsinfo.FSI_Nxt_Free, 4, 1, img); } if(fatcat.fsinfo.FSI_Free_Count < 1){ free = FindClusterInfo(fatcat.fsinfo.FSI_Nxt_Free + 1); if(free.firstSectors[0] != 0){ } } else { // No clusters are free free.firstSectors[0] = 0x00; } return free; }
unsigned int setdirclus(struct directory * dir){ struct cluster temp; unsigned int clusval = 0; dir->cluster = malloc(sizeof(struct cluster)); clusval = dir->FstClusHi; clusval = clusval << 1; clusval = clusval | dir->FstClusLO; clusval = clusval == 0x00 ? BPB_RootClus : clusval; temp = FindClusterInfo(clusval); #ifdef _DEBUGGING printf("\nSetting Cluster info"); printf("\nCLUSTER VALUE: %d\n", clusval); #endif memcpy(dir->cluster, &temp, sizeof(struct cluster)); return 0; }
static void ParseMapInfoLower (MapInfoHandler *handlers, const char *strings[], level_pwad_info_t *levelinfo, cluster_info_t *clusterinfo, DWORD flags) { int entry; MapInfoHandler *handler; byte *info; info = levelinfo ? (byte *)levelinfo : (byte *)clusterinfo; while (SC_GetString ()) { if (SC_MatchString (MapInfoTopLevel) != -1) { SC_UnGet (); break; } entry = SC_MustMatchString (strings); handler = handlers + entry; switch (handler->type) { case MITYPE_IGNORE: break; case MITYPE_EATNEXT: SC_MustGetString (); break; case MITYPE_INT: SC_MustGetNumber (); *((int *)(info + handler->data1)) = sc_Number; break; case MITYPE_FLOAT: SC_MustGetFloat (); *((float *)(info + handler->data1)) = sc_Float; break; case MITYPE_COLOR: { SC_MustGetString (); std::string string = V_GetColorStringByName (sc_String); if (string.length()) { *((DWORD *)(info + handler->data1)) = V_GetColorFromString (NULL, string.c_str()); } else { *((DWORD *)(info + handler->data1)) = V_GetColorFromString (NULL, sc_String); } } break; case MITYPE_MAPNAME: SC_MustGetString (); if (IsNum (sc_String)) { int map = atoi (sc_String); sprintf (sc_String, "MAP%02d", map); } strncpy ((char *)(info + handler->data1), sc_String, 8); break; case MITYPE_LUMPNAME: SC_MustGetString (); uppercopy ((char *)(info + handler->data1), sc_String); break; case MITYPE_SKY: SC_MustGetString (); // get texture name; uppercopy ((char *)(info + handler->data1), sc_String); SC_MustGetFloat (); // get scroll speed //if (HexenHack) //{ // *((fixed_t *)(info + handler->data2)) = sc_Number << 8; //} //else //{ // *((fixed_t *)(info + handler->data2)) = (fixed_t)(sc_Float * 65536.0f); //} break; case MITYPE_SETFLAG: flags |= handler->data1; break; case MITYPE_SCFLAGS: flags = (flags & handler->data2) | handler->data1; break; case MITYPE_CLUSTER: SC_MustGetNumber (); *((int *)(info + handler->data1)) = sc_Number; if (HexenHack) { cluster_info_t *clusterH = FindClusterInfo (sc_Number); if (clusterH) clusterH->flags |= CLUSTER_HUB; } break; case MITYPE_STRING: SC_MustGetString (); ReplaceString ((const char **)(info + handler->data1), sc_String); break; case MITYPE_CSTRING: SC_MustGetString (); strncpy ((char *)(info + handler->data1), sc_String, handler->data2); *((char *)(info + handler->data1 + handler->data2)) = '\0'; break; } } if (levelinfo) levelinfo->flags = flags; else clusterinfo->flags = flags; }
void G_WorldDone (void) { cluster_info_t *nextcluster; cluster_info_t *thiscluster; gameaction = ga_worlddone; if (level.flags & LEVEL_CHANGEMAPCHEAT) return; thiscluster = FindClusterInfo (level.cluster); if (strncmp (nextlevel, "enDSeQ", 6) == 0) { FName endsequence = ENamedName(strtol(nextlevel.GetChars()+6, NULL, 16)); // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewherw. if (endsequence == NAME_Inter_Strife) { if (players[0].mo->FindInventory (QuestItemClasses[24]) || players[0].mo->FindInventory (QuestItemClasses[27])) { endsequence = NAME_Inter_Strife_Good; } else { endsequence = NAME_Inter_Strife_Sad; } } F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder, thiscluster->cdtrack, thiscluster->cdid, thiscluster->FinaleFlat, thiscluster->ExitText, thiscluster->flags & CLUSTER_EXITTEXTINLUMP, thiscluster->flags & CLUSTER_FINALEPIC, thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, true, endsequence); } else { nextcluster = FindClusterInfo (FindLevelInfo (nextlevel)->cluster); if (nextcluster->cluster != level.cluster && !deathmatch) { // Only start the finale if the next level's cluster is different // than the current one and we're not in deathmatch. if (nextcluster->EnterText.IsNotEmpty()) { F_StartFinale (nextcluster->MessageMusic, nextcluster->musicorder, nextcluster->cdtrack, nextcluster->cdid, nextcluster->FinaleFlat, nextcluster->EnterText, nextcluster->flags & CLUSTER_ENTERTEXTINLUMP, nextcluster->flags & CLUSTER_FINALEPIC, nextcluster->flags & CLUSTER_LOOKUPENTERTEXT, false); } else if (thiscluster->ExitText.IsNotEmpty()) { F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder, thiscluster->cdtrack, nextcluster->cdid, thiscluster->FinaleFlat, thiscluster->ExitText, thiscluster->flags & CLUSTER_EXITTEXTINLUMP, thiscluster->flags & CLUSTER_FINALEPIC, thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, false); } } } }
void G_DoCompleted (void) { int i; gameaction = ga_nothing; if (gamestate == GS_TITLELEVEL) { level.MapName = nextlevel; G_DoLoadLevel (startpos, false); startpos = 0; viewactive = true; return; } // [RH] Mark this level as having been visited if (!(level.flags & LEVEL_CHANGEMAPCHEAT)) FindLevelInfo (level.MapName)->flags |= LEVEL_VISITED; if (automapactive) AM_Stop (); wminfo.finished_ep = level.cluster - 1; wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->PName, FTexture::TEX_MiscPatch)]; wminfo.current = level.MapName; if (deathmatch && (dmflags & DF_SAME_LEVEL) && !(level.flags & LEVEL_CHANGEMAPCHEAT)) { wminfo.next = level.MapName; wminfo.LName1 = wminfo.LName0; } else { level_info_t *nextinfo = FindLevelInfo (nextlevel, false); if (nextinfo == NULL || strncmp (nextlevel, "enDSeQ", 6) == 0) { wminfo.next = nextlevel; wminfo.LName1 = NULL; } else { wminfo.next = nextinfo->MapName; wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->PName, FTexture::TEX_MiscPatch)]; } } CheckWarpTransMap (wminfo.next, true); nextlevel = wminfo.next; wminfo.next_ep = FindLevelInfo (wminfo.next)->cluster - 1; wminfo.maxkills = level.total_monsters; wminfo.maxitems = level.total_items; wminfo.maxsecret = level.total_secrets; wminfo.maxfrags = 0; wminfo.partime = TICRATE * level.partime; wminfo.sucktime = level.sucktime; wminfo.pnum = consoleplayer; wminfo.totaltime = level.totaltime; for (i=0 ; i<MAXPLAYERS ; i++) { wminfo.plyr[i].in = playeringame[i]; wminfo.plyr[i].skills = players[i].killcount; wminfo.plyr[i].sitems = players[i].itemcount; wminfo.plyr[i].ssecret = players[i].secretcount; wminfo.plyr[i].stime = level.time; memcpy (wminfo.plyr[i].frags, players[i].frags , sizeof(wminfo.plyr[i].frags)); wminfo.plyr[i].fragcount = players[i].fragcount; } // [RH] If we're in a hub and staying within that hub, take a snapshot // of the level. If we're traveling to a new hub, take stuff from // the player and clear the world vars. If this is just an // ordinary cluster (not a hub), take stuff from the player, but // leave the world vars alone. cluster_info_t *thiscluster = FindClusterInfo (level.cluster); cluster_info_t *nextcluster = FindClusterInfo (wminfo.next_ep+1); // next_ep is cluster-1 EFinishLevelType mode; if (thiscluster != nextcluster || deathmatch || !(thiscluster->flags & CLUSTER_HUB)) { if (nextcluster->flags & CLUSTER_HUB) { mode = FINISH_NextHub; } else { mode = FINISH_NoHub; } } else { mode = FINISH_SameHub; } // Intermission stats for entire hubs G_LeavingHub(mode, thiscluster, &wminfo); for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { // take away appropriate inventory G_PlayerFinishLevel (i, mode, changeflags); } } if (mode == FINISH_SameHub) { // Remember the level's state for re-entry. if (!(level.flags2 & LEVEL2_FORGETSTATE)) { G_SnapshotLevel (); // Do not free any global strings this level might reference // while it's not loaded. FBehavior::StaticLockLevelVarStrings(); } else { // Make sure we don't have a snapshot lying around from before. level.info->ClearSnapshot(); } } else { // Forget the states of all existing levels. G_ClearSnapshots (); if (mode == FINISH_NextHub) { // Reset world variables for the new hub. P_ClearACSVars(false); } level.time = 0; level.maptime = 0; } if (!deathmatch && ((level.flags & LEVEL_NOINTERMISSION) || ((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB)))) { G_WorldDone (); return; } gamestate = GS_INTERMISSION; viewactive = false; automapactive = false; // [RH] If you ever get a statistics driver operational, adapt this. // if (statcopy) // memcpy (statcopy, &wminfo, sizeof(wminfo)); WI_Start (&wminfo); }
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill) { level_info_t *nextinfo = NULL; if (unloading) { Printf (TEXTCOLOR_RED "Unloading scripts cannot exit the level again.\n"); return; } if (levelname == NULL || *levelname == 0) { // end the game levelname = NULL; if (!level.NextMap.Compare("enDSeQ",6)) { nextlevel = level.NextMap; // If there is already an end sequence please leave it alone! } else { nextlevel.Format("enDSeQ%04x", int(gameinfo.DefaultEndSequence)); } } else if (strncmp(levelname, "enDSeQ", 6) != 0) { nextinfo = FindLevelInfo (levelname, false); if (nextinfo != NULL) { level_info_t *nextredir = nextinfo->CheckLevelRedirect(); if (nextredir != NULL) { nextinfo = nextredir; } } nextlevel = nextinfo->MapName; } else { nextlevel = levelname; } if (nextSkill != -1) NextSkill = nextSkill; if (flags & CHANGELEVEL_NOINTERMISSION) { level.flags |= LEVEL_NOINTERMISSION; } cluster_info_t *thiscluster = FindClusterInfo (level.cluster); cluster_info_t *nextcluster = nextinfo? FindClusterInfo (nextinfo->cluster) : NULL; startpos = position; gameaction = ga_completed; if (nextinfo != NULL) { if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB))) { if (nextinfo->flags2 & LEVEL2_RESETINVENTORY) { flags |= CHANGELEVEL_RESETINVENTORY; } if (nextinfo->flags2 & LEVEL2_RESETHEALTH) { flags |= CHANGELEVEL_RESETHEALTH; } } } changeflags = flags; bglobal.End(); //Added by MC: // [RH] Give scripts a chance to do something unloading = true; FBehavior::StaticStartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true); unloading = false; STAT_ChangeLevel(nextlevel); if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) { if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster)) NoWipe = 35; D_DrawIcon = "TELEICON"; } for(int i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { player_t *player = &players[i]; // Un-crouch all players here. player->Uncrouch(); // If this is co-op, respawn any dead players now so they can // keep their inventory on the next map. if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN) && !deathmatch && player->playerstate == PST_DEAD) { // Copied from the end of P_DeathThink [[ player->cls = NULL; // Force a new class if the player is using a random class player->playerstate = PST_REBORN; if (player->mo->special1 > 2) { player->mo->special1 = 0; } // ]] G_DoReborn(i, false); } } } }
void G_InitLevelLocals () { level_info_t *info; BaseBlendA = 0.0f; // Remove underwater blend effect, if any NormalLight.Maps = realcolormaps; // [BB] Instead of just setting the color, we also have to reset Desaturate and build the lights. NormalLight.ChangeColor (PalEntry (255, 255, 255), 0); level.gravity = sv_gravity * 35/TICRATE; level.aircontrol = (fixed_t)(sv_aircontrol * 65536.f); level.teamdamage = teamdamage; level.flags = 0; level.flags2 = 0; info = FindLevelInfo (level.MapName); level.info = info; level.skyspeed1 = info->skyspeed1; level.skyspeed2 = info->skyspeed2; level.skytexture1 = TexMan.GetTexture(info->SkyPic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); level.skytexture2 = TexMan.GetTexture(info->SkyPic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); level.fadeto = info->fadeto; level.cdtrack = info->cdtrack; level.cdid = info->cdid; level.FromSnapshot = false; if (level.fadeto == 0) { R_SetDefaultColormap (info->FadeTable); if (strnicmp (info->FadeTable, "COLORMAP", 8) != 0) { level.flags |= LEVEL_HASFADETABLE; } /* } else { NormalLight.ChangeFade (level.fadeto); */ } level.airsupply = info->airsupply*TICRATE; level.outsidefog = info->outsidefog; level.WallVertLight = info->WallVertLight*2; level.WallHorizLight = info->WallHorizLight*2; if (info->gravity != 0.f) { level.gravity = info->gravity * 35/TICRATE; } if (info->aircontrol != 0.f) { level.aircontrol = (fixed_t)(info->aircontrol * 65536.f); } if (info->teamdamage != 0.f) { level.teamdamage = info->teamdamage; } G_AirControlChanged (); cluster_info_t *clus = FindClusterInfo (info->cluster); level.partime = info->partime; level.sucktime = info->sucktime; level.cluster = info->cluster; level.clusterflags = clus ? clus->flags : 0; level.flags |= info->flags; level.flags2 |= info->flags2; level.levelnum = info->levelnum; level.Music = info->Music; level.musicorder = info->musicorder; level.LevelName = level.info->LookupLevelName(); level.NextMap = info->NextMap; level.NextSecretMap = info->NextSecretMap; compatflags.Callback(); compatflags2.Callback(); NormalLight.ChangeFade (level.fadeto); level.DefaultEnvironment = info->DefaultEnvironment; level.DefaultSkybox = NULL; }
void DrawHUD() { player_t * CPlayer = StatusBar->CPlayer; // [BB] The player may not have a body while connecting. if ( CPlayer->mo == NULL ) return; if (HudFont==NULL) HUD_InitHud(); players[consoleplayer].inventorytics = 0; if (hud_althudscale && SCREENWIDTH>640) { hudwidth=SCREENWIDTH/2; if (hud_althudscale == 2) { // Optionally just double the pixels to reduce scaling artifacts. hudheight=SCREENHEIGHT/2; } else { if (WidescreenRatio == 4) { hudheight = hudwidth * 30 / BaseRatioSizes[WidescreenRatio][3]; // BaseRatioSizes is inverted for this mode } else { hudheight = hudwidth * 30 / (48*48/BaseRatioSizes[WidescreenRatio][3]); } } } else { hudwidth=SCREENWIDTH; hudheight=SCREENHEIGHT; } if (!automapactive) { int i; // No HUD in the title level! if (gamestate == GS_TITLELEVEL || !CPlayer) return; if (!deathmatch) DrawStatus(CPlayer, 5, hudheight-50); else { DrawStatus(CPlayer, 5, hudheight-75); // [TP] Only draw frags if not playing in teams if (( GAMEMODE_GetCurrentFlags() & GMF_PLAYERSONTEAMS ) == 0 ) DrawFrags(CPlayer, 5, hudheight-70); } // [TP] Only draw health and armor if we are allowed to know those stats. Also don't // draw spectator's health/armor stats. if ( ShouldDrawHealth( CPlayer )) { DrawHealth(CPlayer->health, 5, hudheight-45); // Yes, that doesn't work properly for Hexen but frankly, I have no // idea how to make a meaningful value out of Hexen's armor system! DrawArmor(CPlayer->mo->FindInventory(RUNTIME_CLASS(ABasicArmor)), 5, hudheight-20); } // [TP] Draw team stuff. DrawTeamScores( 10, hudheight - 90 ); i=DrawKeys(CPlayer, hudwidth-4, hudheight-10); i=DrawAmmo(CPlayer, hudwidth-5, i); DrawWeapons(CPlayer, hudwidth-5, i); DrawInventory(CPlayer, 144, hudheight-28); if (CPlayer->camera && CPlayer->camera->player) { StatusBar->DrawCrosshair(); } if (idmypos) DrawCoordinates(CPlayer); } else { char printstr[256]; int seconds; cluster_info_t *thiscluster = FindClusterInfo (level.cluster); bool hub = !!(thiscluster->flags&CLUSTER_HUB); int length=8*SmallFont->GetCharWidth('0'); int fonth=SmallFont->GetHeight()+1; int bottom=hudheight-1; if (am_showtotaltime) { seconds = level.totaltime / TICRATE; mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_ttim, printstr, hudwidth-length, bottom, FRACUNIT); bottom -= fonth; } if (am_showtime) { seconds = level.time /TICRATE; mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_time, printstr, hudwidth-length, bottom, FRACUNIT); bottom -= fonth; // Single level time for hubs if (level.clusterflags&CLUSTER_HUB) { seconds= level.maptime /TICRATE; mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_ltim, printstr, hudwidth-length, bottom, FRACUNIT); } } mysnprintf(printstr, countof(printstr), "%s: %s", level.mapname, level.LevelName.GetChars()); screen->DrawText(SmallFont, hudcolor_titl, 1, hudheight-fonth-1, printstr, DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE); DrawCoordinates(CPlayer); } }