/// <summary> /// Constructor /// </summary> /// <param name="ultima5Directory">ultima 5 data and save game directory</param> public World(string ultima5Directory) : base() { _u5Directory = ultima5Directory; DataOvlRef = new DataOvlReference(_u5Directory); SmallMapRef = new SmallMapReferences(DataOvlRef); // build the overworld map OverworldMap = new LargeMap(_u5Directory, LargeMap.Maps.Overworld, _tileOverrides); // build the underworld map UnderworldMap = new LargeMap(_u5Directory, LargeMap.Maps.Underworld, _tileOverrides); SpriteTileReferences = new TileReferences(DataOvlRef.StringReferences); InvRef = new InventoryReferences(); LargeMapRef = new LargeMapLocationReferences(DataOvlRef); AllSmallMaps = new SmallMaps(SmallMapRef, _u5Directory, SpriteTileReferences, _tileOverrides); MoonPhaseRefs = new MoonPhaseReferences(DataOvlRef); State = new GameState(_u5Directory, DataOvlRef); // build all combat maps from the Combat Map References foreach (CombatMapReference.SingleCombatMapReference combatMapRef in _combatMapRef.MapReferenceList) { CombatMap combatMap = new CombatMap(_u5Directory, combatMapRef, _tileOverrides); } // build a "look" table for all tiles LookRef = new Look(_u5Directory); // build the sign tables SignRef = new Signs(_u5Directory); TalkScriptsRef = new TalkScripts(_u5Directory, DataOvlRef); // build the NPC tables NpcRef = new NonPlayerCharacterReferences(_u5Directory, SmallMapRef, TalkScriptsRef, State); ShoppeKeeperDialogueReference = new ShoppeKeeperDialogueReference(_u5Directory, DataOvlRef, NpcRef, State.PlayerInventory); // sadly I have to initialize this after the NPCs are created because there is a circular dependency State.InitializeVirtualMap(SmallMapRef, AllSmallMaps, LargeMapRef, OverworldMap, UnderworldMap, NpcRef, SpriteTileReferences, State, NpcRef, InvRef); if (State.Location != SmallMapReferences.SingleMapReference.Location.Britannia_Underworld) { State.TheVirtualMap.LoadSmallMap(SmallMapRef.GetSingleMapByLocation(State.Location, State.Floor), State.CharacterRecords, true); } else { State.TheVirtualMap.LoadLargeMap(LargeMap.Maps.Overworld); } }
// left over structure /* [StructLayout(LayoutKind.Sequential, Pack = 1)] * private unsafe struct NPC_Info * { * NPC_Schedule schedule[32]; * fixed byte type[32]; // merchant, guard, etc. * fixed byte dialog_number[32]; * };*/ #endregion #region Initialization and Constructor routines /// <summary> /// Initialize NPCs from a particular small map master file set /// </summary> /// <param name="u5Directory">Directory with Ultima 5</param> /// <param name="mapMaster">The master map from which to load</param> /// <param name="smallMapRef">Small map reference to help link NPCs to a map</param> private void InitializeNPCs(string u5Directory, SmallMapReferences.SingleMapReference.SmallMapMasterFiles mapMaster, SmallMapReferences smallMapRef, TalkScripts talkScriptsRef, GameState gameStateRef) { // open the appropriate NPC data file string dataFilenameAndPath = Path.Combine(u5Directory, SmallMapReferences.SingleMapReference.GetNPCFilenameFromMasterFile(mapMaster)); // load the file into memory List <byte> npcData = Utils.GetFileAsByteList(dataFilenameAndPath); for (int nTown = 0; nTown < TOWNS_PER_NPCFILE; nTown++) { // fresh collections for each major loop to guarantee they are clean List <NonPlayerCharacterReference.NPC_Schedule> schedules = new List <NonPlayerCharacterReference.NPC_Schedule>(NPCS_PER_TOWN); List <byte> npcTypes = new List <byte>(NPCS_PER_TOWN); List <byte> npcDialogNumber = new List <byte>(NPCS_PER_TOWN); SmallMapReferences.SingleMapReference.Location location = smallMapRef.GetLocationByIndex(mapMaster, nTown); SmallMapReferences.SingleMapReference singleMapRef = smallMapRef.GetSingleMapByLocation(location, 0); //sing = SmallMapRef.GetSingleMapByLocation(SmallMapRef.GetLocationByIndex(mapMaster, nTown); int townOffset = (TOWN_OFFSET_SIZE * nTown); // bajh: I know this could be done in a single loop, but it would be so damn ugly that I honestly don't even want to both // read through the schedules first int count = 0; // start at the town offset, incremenet by an NPC record each time, for 32 loops for (int offset = townOffset; count < NPCS_PER_TOWN; offset += SCHEDULE_OFFSET_SIZE, count++) { NonPlayerCharacterReference.NPC_Schedule sched = (NonPlayerCharacterReference.NPC_Schedule)Utils.ReadStruct(npcData, offset, typeof(NonPlayerCharacterReference.NPC_Schedule)); schedules.Add(sched); } // bajh: just shoot me if I ever have to write this again - why on earth did LB write all of his data in different formats! // these are single byte, so we can capture them just by jumping to their offsets count = 0; for (int offset = townOffset; count < NPCS_PER_TOWN; offset++, count++) { // add NPC type npcTypes.Add(npcData[offset + STARTING_NPC_TYPE_TOWN_OFFSET]); // add NPC dialog # npcDialogNumber.Add(npcData[offset + STARTING_NPC_DIALOG_TOWN_OFFSET]); } List <byte> keySpriteList = gameStateRef.NonPlayerCharacterKeySprites.GetAsByteList(); // go over all of the NPCs, create them and add them to the collection for (int nNpc = 0; nNpc < NPCS_PER_TOWN; nNpc++) { NonPlayerCharacterReference npc = new NonPlayerCharacterReference(location, gameStateRef, schedules[nNpc], npcTypes[nNpc], npcDialogNumber[nNpc], nNpc, talkScriptsRef.GetTalkScript(mapMaster, npcDialogNumber[nNpc]), (int)(keySpriteList[nNpc] + 100)); npcs.Add(npc); // we also create a quick lookup table by location but first need to check that there is an initialized list inside if (!locationToNPCsDictionary.ContainsKey(singleMapRef.MapLocation)) { locationToNPCsDictionary.Add(singleMapRef.MapLocation, new List <NonPlayerCharacterReference>()); } locationToNPCsDictionary[singleMapRef.MapLocation].Add(npc); } } }
/// <summary> /// Construct all of the non player characters across all of the SmallMaps /// </summary> /// <param name="u5Directory">the directory with Ultima 5 data files</param> /// <param name="smallMapRef">The small map reference</param> /// <param name="talkScriptsRe">Talk script references</param> public NonPlayerCharacterReferences(string u5Directory, SmallMapReferences smallMapRef, TalkScripts talkScriptsRef, GameState gameStateRef) { InitializeNPCs(u5Directory, SmallMapReferences.SingleMapReference.SmallMapMasterFiles.Castle, smallMapRef, talkScriptsRef, gameStateRef); InitializeNPCs(u5Directory, SmallMapReferences.SingleMapReference.SmallMapMasterFiles.Towne, smallMapRef, talkScriptsRef, gameStateRef); InitializeNPCs(u5Directory, SmallMapReferences.SingleMapReference.SmallMapMasterFiles.Keep, smallMapRef, talkScriptsRef, gameStateRef); InitializeNPCs(u5Directory, SmallMapReferences.SingleMapReference.SmallMapMasterFiles.Dwelling, smallMapRef, talkScriptsRef, gameStateRef); }
public World(string ultima5Directory) : base() { u5Directory = ultima5Directory; // build the overworld map OverworldMap = new LargeMap(u5Directory, LargeMap.Maps.Overworld); // build the underworld map UnderworldMap = new LargeMap(u5Directory, LargeMap.Maps.Underworld); DataOvlRef = new DataOvlReference(u5Directory); SpriteTileReferences = new TileReferences(DataOvlRef.StringReferences); SmallMapRef = new SmallMapReferences(DataOvlRef); LargeMapRef = new LargeMapReference(DataOvlRef, SmallMapRef); AllSmallMaps = new SmallMaps(SmallMapRef, u5Directory, SpriteTileReferences); State = new GameState(u5Directory, DataOvlRef); //CharacterRecord character = State.GetCharacterFromParty(0); //CharacterRecord character3 = State.GetCharacterFromParty(3); //CharacterRecord character4 = State.GetCharacterFromParty(4); //character.Equipped.Amulet = DataOvlReference.EQUIPMENT.Ankh; //CharacterRecord character2 = State.GetCharacterFromParty(0); // build all the small maps from the Small Map reference //foreach (SmallMapReferences.SingleMapReference mapRef in SmallMapRef.MapReferenceList) //{ // // now I can go through each and every reference // SmallMap smallMap = new SmallMap(u5Directory, mapRef); // smallMaps.Add(smallMap); // //U5Map.PrintMapSection(smallMap.RawMap, 0, 0, 32, 32); //} // build all combat maps from the Combat Map References foreach (CombatMapReference.SingleCombatMapReference combatMapRef in combatMapRef.MapReferenceList) { CombatMap combatMap = new CombatMap(u5Directory, combatMapRef); //System.Console.WriteLine("\n"); //System.Console.WriteLine(combatMap.Description); //Map.PrintMapSection(combatMap.RawMap, 0, 0, 11, 11); } // build a "look" table for all tiles LookRef = new Look(ultima5Directory); // build the sign tables SignRef = new Signs(ultima5Directory); //Signs.Sign sign = SignRef.GetSign(SmallMapReferences.SingleMapReference.Location.Yew, 16, 2); Signs.Sign sign = SignRef.GetSign(42); string str = sign.SignText; TalkScriptsRef = new TalkScripts(u5Directory, DataOvlRef); // build the NPC tables NpcRef = new NonPlayerCharacterReferences(ultima5Directory, SmallMapRef, TalkScriptsRef, State); //CharAnimationStates = new MapCharacterAnimationStates(State, SpriteTileReferences); //CharStates = new MapCharacterStates(State, SpriteTileReferences); // sadly I have to initilize this after the Npcs are created because there is a circular dependency State.InitializeVirtualMap(SmallMapRef, AllSmallMaps, LargeMapRef, OverworldMap, UnderworldMap, NpcRef, SpriteTileReferences, State, NpcRef); if (State.Location != SmallMapReferences.SingleMapReference.Location.Britainnia_Underworld) { State.TheVirtualMap.LoadSmallMap(SmallMapRef.GetSingleMapByLocation(State.Location, State.Floor), true); } else { State.TheVirtualMap.LoadLargeMap(LargeMap.Maps.Overworld); } //State.TheVirtualMap.LoadSmallMap() //State.PlayerInventory.MagicSpells.Items[Spell.SpellWords.An_Ex_Por].GetLiteralTranslation(); //State.TheVirtualMap.LoadSmallMap(SmallMapRef.GetSingleMapByLocation(SmallMapReferences.SingleMapReference.Location.Serpents_Hold, 0), false); //int nSpriteGuess = State.TheVirtualMap.GuessTile(new Point2D(15, 15)); //NpcRef.GetNonPlayerCharacter(SmallMapReferences.SingleMapReference.Location.Britain, new Point2D(0, 31), 0); //State.Year = 100; //State.Month = 13; //State.Day = 28; //State.Hour = 22; //State.Minute = 2; //Conversation convo = new Conversation(NpcRef.NPCs[21]); // dunkworth // Conversation convo = new Conversation(NpcRef.NPCs[296], State, DataOvlRef); // Gwenno // 19 = Margarett // NpcRef.NPCs[296].Script.PrintComprehensiveScript(); int count = 0; if (false) { foreach (NonPlayerCharacterReference npc in NpcRef.NPCs) { if (npc.NPCType != 0 && npc.Script != null) { Console.WriteLine(""); Console.WriteLine("---- SCRIPT for " + npc.Name.Trim() + " -----"); //Npc.Script.PrintScript(); npc.Script.PrintComprehensiveScript(); if (npc.Name.Trim() == "Geoffrey") { Console.WriteLine(npc.NPCType.ToString()); } } count++; } } // Scally //Conversation convo = new Conversation(NpcRef.NPCs[0xe6], State, DataOvlRef); // Bidney //Conversation convo = new Conversation(NpcRef.NPCs[0xe8], State); // Lord Dalgrin //Conversation convo = new Conversation(NpcRef.NPCs[0xea], State); // Geoffery //Conversation convo = new Conversation(NpcRef.NPCs[0xec], State, DataOvlRef); // Tierra //Conversation convo = new Conversation(NpcRef.NPCs[0xeb], State, DataOvlRef); // Conversation.EnqueuedScriptItem enqueuedScriptItemDelegate = new Conversation.EnqueuedScriptItem(this.EnqueuedScriptItem); // convo.EnqueuedScriptItemCallback += enqueuedScriptItemDelegate; // convo.BeginConversation(); //0x48 or 0x28 //Console.WriteLine("Shutting down... Hit any key..."); //Console.ReadKey(false); }