/// <summary> /// internal function /// Check quest links to BaseCreature.Id /// </summary> private static void CheckQuest(Hashtable _cArr, int _cId, BaseQuest bq, bool addQuest, string nameVar) { if (_cId > 0) //CreatureId - link from quest (npcId, SpeakToId, DeliveryId ) { if (_cArr.ContainsKey(_cId)) // creatures array have this CreatureId { if (((BaseCreature)_cArr[_cId]) is BaseNPC) //this Id is BaseNPC class old { if (addQuest) { AddQuest(_cId, bq.Id); //add int Id to array } } else { string text = string.Format("* {0} have bad \"{1} = {2};\" link", bq.GetType().Name, nameVar, _cId); string data1 = string.Format("\t> Need change \"BaseCreature\" to \"BaseNPC\" in inherite (header) area."); string data2 = string.Format("\t-> Ex: \"public class {0}: BaseNPC\"", ((BaseCreature)_cArr[_cId]).GetType().Name); AddErr(text, data1, data2); } } else { string text = string.Format("* {0} have bad \"{1}\" link ( Creature \"Id = {2}\" is not exist: need remark this and use questisBugged or write this creature script )", bq.GetType().Name, nameVar, _cId); string data1 = string.Format("\t> Need create this creature \"Id = {0};\"", _cId); string data2 = string.Format("\t> Or Remark line \"//{1} = {0};\" and use \"questIsBugged = true;\"", _cId, nameVar); AddErr(text, data1, data2); } } else { if (addQuest) //if this is a npcId { string text = string.Format("* {0} have bad \"{1} = ?;\" link ( need use Id from NPC questOwner )", bq.GetType().Name, nameVar); string data1 = string.Format("\t> Need search and find this creature questOwner and then use Id number to \"npcId = (Id);\""); string data2 = string.Format("\t> Or create this creature and then use it number.."); AddErr(text, data1, data2); } } }
/// <summary> /// BaseQuest[] for npcId /// </summary> public static BaseQuest[] GetQuestsFor(int npcId) { if (_NPCQuests.ContainsKey(npcId)) { if (_NPCQuests[npcId] is BaseQuest[]) { return((BaseQuest[])_NPCQuests[npcId]); //optimized } else if (_NPCQuests[npcId] is ArrayList) { ArrayList quests = new ArrayList(); foreach (int qId in (_NPCQuests[npcId] as ArrayList)) { BaseQuest bq = World.CreateQuestById(qId); if (bq != null) { quests.Add(bq); } } return((BaseQuest[])quests.ToArray(typeof(BaseQuest))); //support un optimized } } return(new BaseQuest[] {}); }
/// <summary> /// onEndQuest /// changed: 02.10.05 /// </summary> public void SetQuestDone( BaseQuest bq, Reward[] rewards ) { int num = 0; foreach( ActiveQuest aq in activeQuests ) { if ( aq != null && bq.Id == aq.Id ) { aq.Done = true; if ( bq.Repeatable ) questsDone[ aq.Id ] = null; // repeat quest support else questsDone[ aq.Id ] = true; // normal quest done QuestUpdateComplete( bq ); //int offset = 4; //Converter.ToBytes( (int)aq.Id, tempBuff, ref offset ); //Send( OpCodes.SMSG_QUESTUPDATE_COMPLETE, tempBuff, offset ); // Output: 'Objective Complete.' // Also marks the quest at questlog with (Failed) int offset = 4; Converter.ToBytes( (int)aq.Id, tempBuff, ref offset ); // QuestId Converter.ToBytes( (int)0, tempBuff, ref offset ); // Unknown Converter.ToBytes( (int)bq.RewardXp, tempBuff, ref offset ); // xpReceived Converter.ToBytes( (int)bq.RewardGold, tempBuff, ref offset ); // moneyReceived if ( rewards!= null ) { Converter.ToBytes( (int)rewards.Length, tempBuff, ref offset ); // count rewarded items for ( int i=0; i< rewards.Length; i++ ) { Reward rew = rewards[i]; Converter.ToBytes( (int)rew.Id, tempBuff, ref offset ); // reward Id Converter.ToBytes( (int)rew.Amount, tempBuff, ref offset ); // reward Amount } } else Converter.ToBytes( (int)0, tempBuff, ref offset ); Send( OpCodes.SMSG_QUESTGIVER_QUEST_COMPLETE, tempBuff, offset ); RemoveQuest( (byte)num ); break; } num++; } }
/// <summary> /// Quest is Done ? /// </summary> public bool QuestDone( BaseQuest bq ) { return !( questsDone[ bq.Id ] == null ); }
/// <summary> /// onEndQuest /// changed: 01.10.05 /// </summary> public void SetQuestDone( BaseQuest bq ) { SetQuestDone( bq, null ); }
/// <summary> /// Get Active Quest by BaseQuest type /// </summary> public ActiveQuest FindPlayerQuest( BaseQuest bq ) { foreach( ActiveQuest aq in activeQuests ) { if ( aq == null ) continue; if ( aq.Id == bq.Id ) return aq; } return null; }
/// <summary> /// Check exist quest by BaseQuest type /// </summary> public bool HaveQuest( BaseQuest bq ) { return ( bq == null ) ? false : HaveQuest( bq.Id ); }
/// <summary> /// Extract emotion list from bq /// created: 09.10.05 /// </summary> private static qEmote[] getEmoteOnStart( BaseQuest bq ) { if ( bq.onStartQuestCustom != null ) return bq.onStartQuestCustom; if ( BaseQuest.onStartQuestDefault != null ) return BaseQuest.onStartQuestDefault; return null; }
/// <summary> /// total reinitialisation, check and fill quests to arrays /// </summary> public static void Init() { // second initialisation exclude if (status != InitStatus.None || World.Loading) { return; } status = InitStatus.Started; bool haveExeption = false; bool haveWarns = false; try // strongly recomended to use (for exclude server crush if uncorrect scripts) { BaseQuest[] allQuests = GetAllQuestsInWorld(); BaseCreature[] allCreatures = GetAllCreaturesInWorld(); //sort all Creatures by ID Hashtable SortedCreatures = new Hashtable(); foreach (BaseCreature bc in allCreatures) { if (!SortedCreatures.ContainsKey(bc.Id)) { SortedCreatures.Add((int)bc.Id, bc); } else { if (bc.Id > 0) { string text = string.Format("* {0} is already have ( [{2}].Id = {1} )", bc.GetType().Name, bc.Id, ((BaseCreature)(SortedCreatures[bc.Id])).GetType().Name); string data1 = string.Format("\t> Check this creatureId \"{0}\" in each script", bc.Id); AddErr(text, data1); } } if (bc.Quests != null && (bc.GetType().Name != "BaseNPC") && bc.Quests.Length > 0) { string text = string.Format("* {0} already have Quests line", bc.GetType().Name); string data1 = string.Format("\t> Need remove/remark this line \"Quests = new ...\""); string data2 = string.Format("\t-> remark mean \"//Quests = new ...\""); AddErr(text, data1, data2); } } // some text output if (errors.Count > 0) { errors.Insert(0, ""); errors.Insert(0, "Start checking Creatures [Server.Creatures]"); AddErrHeader(""); AddErrHeader("Start checking Quests [Server.Quests]"); AddErrHeader(""); haveWarns = true; } // checking and fill quest arrays foreach (BaseQuest bq in allQuests) { CheckQuest(SortedCreatures, bq.NPCId, bq, true, "NPCId"); //checks NPC Id CheckQuest(SortedCreatures, bq.NPCTargetId, bq, false, "NpcTargetId"); //checks Target Id if (!bq.QuestIsBugged) { if (bq.PreviousQuest > 0 && !QuestExists(bq.PreviousQuest)) //checks PreviousQuest { string text = string.Format("* {0} have bad link to PreviousQuest (prev quest is not exist)", bq.GetType().Name); string data1 = string.Format("\t> Try do quest by number {0}", bq.PreviousQuest); string data2 = string.Format("\t> Or comment this line \"previousQuest = {0};\"", bq.PreviousQuest); AddErr(text, data1, data2); } if (bq.NextQuest > 0 && !QuestExists(bq.NextQuest)) //checks NextQuest { string text = string.Format("* {0} have bad link to NextQuest (next quest is not exist)", bq.GetType().Name); string data1 = string.Format("\t> Try do quest by number {0}", bq.NextQuest); string data2 = string.Format("\t> Or comment this line \"nextQuest = {0};\"", bq.NextQuest); AddErr(text, data1, data2); } if (bq.QuestFlags == 0) //checks for bad questflag { string text = string.Format("* {0} have bad questFlags ( value is 0 )", bq.GetType().Name); string data1 = string.Format("\t> Try change value to \"questFlags = 0x20;\""); AddErr(text, data1); } } } // some text output if (errors.Count > 0 && !haveWarns) { errors.Insert(0, ""); errors.Insert(0, "Start checking Quests [Server.Quests]"); } // optimisations (this operation allow use this code convertions only one time and then free some processor time ) // int[] -> BaseQuest[] for each NPC Hashtable tmp = new Hashtable(); foreach (int cId in _NPCQuests.Keys) { ArrayList list = (ArrayList)_NPCQuests[cId]; ArrayList quests = new ArrayList(); foreach (int qId in list) { BaseQuest bq = World.CreateQuestById(qId); if (bq != null) { quests.Add(bq); } } tmp.Add(cId, (BaseQuest[])quests.ToArray(typeof(BaseQuest))); } _NPCQuests.Clear(); _NPCQuests = tmp; //End Of Optimisations } catch (Exception e) { haveExeption = true; AddErrHeader(""); AddErrHeader("Exeption: {0}", e); AddErrHeader(""); AddErrHeader("message: {0}", e.Message); AddErrHeader("source: {0}", e.Source); AddErrHeader("stack trace: {0}", e.StackTrace); AddErrHeader("inner exeption: {0}", e.InnerException); AddErrHeader("target site: {0}", e.TargetSite); AddErrHeader("help link: {0}", e.HelpLink); } finally { } // each NPC can use this section after initialisations if (!haveExeption) { status = InitStatus.Done; // if have exeprion - not allow use quests } }
public void AddMenu(string menu, BaseQuest bq) { menus.Add(menu); quests.Add(bq); }
//===================================================================== //SMSG_QUESTUPDATE_FAILED // { // uint32 questID // } //Output: '%s failed.' /// <summary> /// Quest Update failed /// created: 01.10.05 /// </summary> public void QuestUpdateFailed( BaseQuest bq ) { int offset = 4; Converter.ToBytes( (int)bq.Id, tempBuff, ref offset ); Send( OpCodes.SMSG_QUESTUPDATE_FAILED, tempBuff, offset ); }
/// <summary> /// internal function /// Check quest links to BaseCreature.Id /// </summary> private static void CheckQuest( Hashtable _cArr, int _cId, BaseQuest bq, bool addQuest, string nameVar ) { if ( _cId > 0 )//CreatureId - link from quest (npcId, SpeakToId, DeliveryId ) { if ( _cArr.ContainsKey( _cId ) )// creatures array have this CreatureId { if ( ((BaseCreature)_cArr[ _cId ]) is BaseNPC )//this Id is BaseNPC class old { if ( addQuest ) AddQuest( _cId, bq.Id );//add int Id to array } else { string text = string.Format( "* {0} have bad \"{1} = {2};\" link", bq.GetType().Name, nameVar, _cId ); string data1 = string.Format( "\t> Need change \"BaseCreature\" to \"BaseNPC\" in inherite (header) area." ); string data2 = string.Format( "\t-> Ex: \"public class {0}: BaseNPC\"", ((BaseCreature)_cArr[ _cId ]).GetType().Name ); AddErr( text, data1, data2 ); } } else { string text = string.Format( "* {0} have bad \"{1}\" link ( Creature \"Id = {2}\" is not exist: need remark this and use questisBugged or write this creature script )", bq.GetType().Name, nameVar, _cId ); string data1 = string.Format( "\t> Need create this creature \"Id = {0};\"", _cId ); string data2 = string.Format( "\t> Or Remark line \"//{1} = {0};\" and use \"questIsBugged = true;\"", _cId, nameVar ); AddErr( text, data1, data2 ); } } else { if ( addQuest )//if this is a npcId { string text = string.Format( "* {0} have bad \"{1} = ?;\" link ( need use Id from NPC questOwner )", bq.GetType().Name, nameVar ); string data1 = string.Format( "\t> Need search and find this creature questOwner and then use Id number to \"npcId = (Id);\"" ); string data2 = string.Format( "\t> Or create this creature and then use it number.." ); AddErr( text, data1, data2 ); } } }
private bool completed; // ( quest is done ) #region Constructors ( public ), changed: 24.09.05 /// <summary> /// Constructor /// 24.09.05: Removed initialisations of arrays /// </summary> public ActiveQuest(BaseQuest bq) { ConstructorInfo [] ct = bq.GetType().GetConstructors(); activeQuest = (BaseQuest)ct[0].Invoke(null); }
private Hashtable npcobj = new Hashtable(); // Changed 24.09.05 ( format: npcobj[int]=int ) #endregion Fields #region Constructors /// <summary> /// Constructor /// 24.09.05: Removed initialisations of arrays /// </summary> public ActiveQuest( BaseQuest bq ) { ConstructorInfo []ct = bq.GetType().GetConstructors(); activeQuest = (BaseQuest)ct[ 0 ].Invoke( null ); }
/// <summary> /// Deserialisation /// changed: 24.09.05 /// </summary> public void Deserialisation( GenericReader gr ) { int version = gr.ReadInt(); switch ( version ) { case 0: // version = 0; { // Delivery obj int nDel = gr.ReadInt(); if ( nDel > 0 ) { for ( int t = 0; t<nDel; t++ ) { int _id = gr.ReadInt(); int _amount = gr.ReadInt(); delivery.Add( _id, _amount ); } } // Npc obj int nNpc = gr.ReadInt(); if ( nNpc > 0 ) { for ( int t = 0; t<nNpc; t++ ) { int _id = gr.ReadInt(); int _amount = gr.ReadInt(); npcobj.Add( _id, _amount ); } } // Areas int nAreas = gr.ReadInt(); if ( nAreas > 0 ) { for ( int t = 0; t<nAreas; t++ ) { areas.Add( gr.ReadInt() ); } } // init section activeQuest = World.CreateQuestById( gr.ReadInt() ); completed = gr.ReadBool(); break; } } }
/// <summary> /// private internal Events on quest selections /// changed: 02.10.05 /// </summary> private void DoQuestEvents( Character c, BaseQuest bq ) { if ( c.QuestDone( bq ) ) return; if ( !c.QuestCompleted( bq ) ) { if ( !c.HaveQuest( bq ) ) { if ( bq.HaveDeliveryObj && !HaveFreeSlot( c ) ) // quest need free slot { c.QuestFailed( qFailedReason.InventoryFull ); } else if ( AmountActiveQuests( c ) >= 20 ) // questLog is full { c.QuestLogIsFull(); } else // can get quest {//need add questEmotion[] on get quest c.ResponseQuestDetails( this, bq.Id, bq.Name, bq.Desc, bq.Details, getEmoteOnStart( bq ) ); //c.ResponseQuestDetails( this, bq.Id, bq.Name, bq.Desc, bq.Details, new qEmote[] { new qEmote( Emote.ONESHOT_TALK, 500 ) } ); } } else { //c.QuestInvalid( qInvalidReason.ReadyHaveThatQuest ); c.SendGossip( this, OnlyQuests ? (int)NPCMenuId.Quests : (int)NPCMenuId.MainMenu, null, null ); //c.ResponseMessage( this, OnlyQuests ? (int)NPCMenuId.Quests : (int)NPCMenuId.MainMenu, bq.ProgressDialog ); } } else if ( c.QuestCompleted( bq ) ) {//need add questEmotion[] on complete quest c.OfferReward( this, bq.Id, bq.FinishTitle, bq.FinishDialog, getEmoteOnEnd( bq ) ); //c.OfferReward( this, bq.Id, bq.FinishTitle, bq.FinishDialog, new qEmote[] { new qEmote( Emote.ONESHOT_TALK, 500 ) } ); } }
/// <summary> /// Quest Completed ? /// </summary> public bool QuestCompleted( BaseQuest bq ) { bool result = false; if ( bq != null ) foreach( ActiveQuest aq in activeQuests ) { if ( aq != null && bq.Id == aq.Id ) { result = aq.Completed; break; } } return result; }
/// <summary> /// Quest for this npc ? /// </summary> public static bool QuestForNPC( BaseQuest bq, BaseNPC npc ) { return bq.HaveNPCTargetId && bq.NPCTargetId == npc.Id; }
/// <summary> /// Quest List /// changed: 04.10.05 /// </summary> public void QuestList( Mobile from, string text, qEmote e, BaseQuest[] quests ) { int offset = 4; Converter.ToBytes( (ulong)from.Guid, tempBuff, ref offset ); // npcGuId Converter.ToBytes( (string)text, tempBuff, ref offset ); // HeaderText Converter.ToBytes( (byte)0, tempBuff, ref offset ); Converter.ToBytes( (int)e.Delay, tempBuff, ref offset ); // Delay To Play Emote (mili secs) Converter.ToBytes( (int)e.emote, tempBuff, ref offset ); // Emote (Wad use EMOTE_ONESHOT_) Converter.ToBytes( (byte)quests.Length, tempBuff, ref offset ); // Amount of quests only 15 allowed foreach ( BaseQuest bq in quests ) { Converter.ToBytes( (int)bq.Id, tempBuff, ref offset ); // QuestId int _qStatus = HaveQuest( bq ) ? 0x03 : 0x05; Converter.ToBytes( (int)_qStatus, tempBuff, ref offset ); // QuestStatus, need test Converter.ToBytes( (int)0, tempBuff, ref offset ); // Unknown Converter.ToBytes( (string)bq.Name, tempBuff, ref offset ); // QuestName Converter.ToBytes( (byte)0, tempBuff, ref offset ); } Send( OpCodes.SMSG_QUESTGIVER_QUEST_LIST, tempBuff, offset ); }
/// <summary> /// Check, for Race, Class, Skills, and Bugable quest /// </summary> private static bool AllowedTo( BaseQuest bq, Character c ) { return ( bq.MinLevel <= c.Level ) && bq.AllowedClass( c ) && bq.AllowedRace( c ) && bq.AllowedSkills( c ) && !bq.QuestIsBugged ; }
//===================================================================== //SMSG_QUESTUPDATE_COMPLETE // { // uint32 questID // } //Output: 'Objective Complete.' //Also marks the quest at questlog with (Failed) /// <summary> /// Quest update compleate /// created: 04.10.05 /// </summary> public void QuestUpdateComplete( BaseQuest bq ) { int offset = 4; Converter.ToBytes( (int)bq.Id, tempBuff, ref offset ); Send( OpCodes.SMSG_QUESTUPDATE_COMPLETE, tempBuff, offset ); }
/// <summary> /// Static function for using in all quests (for smaller code) /// changed: 01.10.05, need mod /// </summary> public static DialogStatus QDS( Mobile questOwner, Character c, BaseQuest bq ) { DialogStatus result = DialogStatus.ChatUnAvailable; if ( questOwner.Reputation( c ) > bq.MinReputation ) { if ( !c.QuestDone( bq ) ) // этот квест уже пройден { if ( !c.HaveQuest( bq ) ) // у чара нету этого квеста { if ( AllowedTo( bq, c ) ) // разрешено выдать, подходит ( расса, класс, скилл ) { if ( bq.PreviousQuest > 0 ) // этот квест из серии, необходимо закончить предыдущий { BaseQuest q = World.CreateQuestById( bq.PreviousQuest ); if ( q != null && c.QuestDone( q ) ) { result = DialogStatus.SingleQuestAvailable; //предыдущий закончен, этот можно получить } } else // квест одиночный или начальный для серии { result = DialogStatus.SingleQuestAvailable; } } } else // Character have this quest already { ActiveQuest aq = c.FindPlayerQuest( bq ); if ( aq.Completed ) // закончен квест, нужно наградить { result = aq.Repeatable ? DialogStatus.RepeatQuestCompleate : DialogStatus.SingleQuestCompleate; } else if ( !QuestForNPC( bq, (BaseNPC)questOwner ) ) // квест не для этого нпс? { result = DialogStatus.QuestUnCompleate; } } } } return result; }