public TriggerControl GetTriggerFromAddress(Nwn2ConversationAddress address)
        {
            if (address == null)
            {
                throw new ArgumentNullException("address");
            }

            if (address.AttachedAs == Sussex.Flip.Core.ScriptType.Conditional)
            {
                return(null);
            }

            NWN2GameModule mod = NWN2Toolset.NWN2ToolsetMainForm.App.Module;

            if (mod == null)
            {
                throw new InvalidOperationException("No module is open.");
            }

            NWN2GameConversation conversation = session.GetConversation(address.Conversation);

            if (conversation == null)
            {
                throw new ArgumentException("Could not find conversation '" + address.Conversation + "' in this module.", "conversation");
            }

            if (NWN2Toolset.NWN2ToolsetMainForm.App.GetViewerForResource(conversation) == null)
            {
                conversation.Demand();
            }

            NWN2ConversationLine line = conversation.GetLineFromGUID(address.LineID);

            if (line == null)
            {
                throw new ArgumentException("Could not find a line with the given ID in conversation '" + address.Conversation + "'.", "conversation");
            }

            return(new DialogueWasSpoken(line.OwningConnector, conversation));
        }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="script"></param>
        /// <param name="attachment">Only return a script if it is attached
        /// in the manner indicated by this parameter.</param>
        /// <returns></returns>
        /// <remarks>This method expects that the NWN2GameScript is already Loaded
        /// (that is, the responsibility for calling Demand() falls to the client.)</remarks>
        public FlipScript GetFlipScript(NWN2GameScript script, Attachment attachment)
        {
            if (script == null)
            {
                throw new ArgumentNullException("script");
            }

            string code, address, naturalLanguage;

            ScriptWriter.ParseNWScript(script.Data, out code, out address, out naturalLanguage);

            ScriptType scriptType = GetScriptType(script);

            if (attachment == Attachment.Ignore)
            {
                return(new FlipScript(code, scriptType, script.Name));
            }

            NWN2GameModule mod = session.GetModule();

            if (mod == null)
            {
                throw new InvalidOperationException("No module is open.");
            }

            Nwn2Address             nwn2Address;
            Nwn2ConversationAddress nwn2ConversationAddress;

            switch (attachment)
            {
            case Attachment.Attached:
                nwn2Address             = Nwn2Address.TryCreate(address);
                nwn2ConversationAddress = Nwn2ConversationAddress.TryCreate(address);
                break;

            case Attachment.AttachedToConversation:
                nwn2Address             = null;
                nwn2ConversationAddress = Nwn2ConversationAddress.TryCreate(address);
                break;

            case Attachment.AttachedToScriptSlot:
                nwn2Address             = Nwn2Address.TryCreate(address);
                nwn2ConversationAddress = null;
                break;

            default:
                nwn2Address             = null;
                nwn2ConversationAddress = null;
                break;
            }

            if (nwn2Address != null)
            {
                try {
                    if (nwn2Address.TargetType == Nwn2Type.Module)
                    {
                        IResourceEntry resource = typeof(NWN2ModuleInformation).GetProperty(nwn2Address.TargetSlot).GetValue(mod.ModuleInfo, null) as IResourceEntry;
                        if (resource != null && resource.ResRef.Value == script.Name)
                        {
                            return(new FlipScript(code, scriptType, script.Name));
                        }
                    }

                    else if (nwn2Address.TargetType == Nwn2Type.Area)
                    {
                        NWN2GameArea area = session.GetArea(nwn2Address.AreaTag);

                        if (area != null)
                        {
                            IResourceEntry resource = typeof(NWN2GameArea).GetProperty(nwn2Address.TargetSlot).GetValue(area, null) as IResourceEntry;
                            if (resource != null && resource.ResRef.Value == script.Name)
                            {
                                return(new FlipScript(code, scriptType, script.Name));
                            }
                        }
                    }

                    else
                    {
                        /*
                         * The script might be attached to a Narrative Threads blueprint:
                         */

                        // First check that if a blueprint which uses this tag as resref exists, it was created by Narrative Threads:

                        if (nt.CreatedByNarrativeThreads(nwn2Address.TargetType, nwn2Address.InstanceTag))
                        {
                            NWN2ObjectType objectType = Nwn2ScriptSlot.GetObjectType(nwn2Address.TargetType).Value;
                            INWN2Blueprint blueprint  = session.GetBlueprint(nwn2Address.InstanceTag.ToLower(), objectType);

                            if (blueprint != null)
                            {
                                IResourceEntry resource = blueprint.GetType().GetProperty(nwn2Address.TargetSlot).GetValue(blueprint, null) as IResourceEntry;
                                if (resource != null && resource.ResRef.Value == script.Name)
                                {
                                    return(new FlipScript(code, scriptType, script.Name));
                                }
                            }
                        }

                        // Check through all OPEN areas.
                        foreach (NWN2GameArea area in mod.Areas.Values)
                        {
                            if (!session.AreaIsOpen(area))
                            {
                                continue;
                            }

                            NWN2InstanceCollection instances = session.GetObjectsByAddressInArea(nwn2Address, area.Tag);

                            if (instances != null)
                            {
                                // Check the script is still attached to the target object in the slot it claims to be,
                                // in at least one instance, and if so add it to the set of scripts to be opened:

                                foreach (INWN2Instance instance in instances)
                                {
                                    IResourceEntry resource = instance.GetType().GetProperty(nwn2Address.TargetSlot).GetValue(instance, null) as IResourceEntry;
                                    if (resource != null && resource.ResRef.Value == script.Name)
                                    {
                                        return(new FlipScript(code, scriptType, script.Name));
                                    }
                                }
                            }
                        }
                    }
                }

                catch (Exception x) {
                    throw new ApplicationException(String.Format("Failed to handle script + '{0}' properly.", script.Name), x);
                }
            }

            else if (nwn2ConversationAddress != null)               // Check through all conversations, regardless of whether they're open.

            {
                NWN2GameConversation conversation = session.GetConversation(nwn2ConversationAddress.Conversation);

                if (conversation == null)
                {
                    return(null);
                }

                if (NWN2Toolset.NWN2ToolsetMainForm.App.GetViewerForResource(conversation) == null)
                {
                    conversation.Demand();
                }

                NWN2ConversationLine line = conversation.GetLineFromGUID(nwn2ConversationAddress.LineID);

                if (line == null)
                {
                    return(null);
                }

                if (line.Actions.Count == 0)
                {
                    return(null);
                }

                IResourceEntry resource = line.Actions[0].Script;
                if (resource != null && resource.ResRef.Value == script.Name)
                {
                    return(new FlipScript(code, scriptType, script.Name));
                }
            }

            return(null);
        }
        /// <summary>
        /// If there already exists a conversation by the name in the module, then it is fetched, otherwise a new is created
        /// </summary>
        /// <param name="questName">The name of the quset</param>
        /// <param name="gender">The gender which will be used in the quest</param>
        /// <param name="lang">The spoken (real world) language</param>
        /// <returns>The conversation</returns>
        private NWN2GameConversation conversationFixer(string questName, BWLanguages.Gender gender, BWLanguages.BWLanguage lang)
        {
            String convName = String.Empty;
            NWN2GameConversation cConversation = null;

            /* If the actor is a creature and does not yet belong to a faction,
             * I set it to be a commoner.
             */
            #region factionSet
            if (actor.type == EnumTypes.actorType.Creature)
                {
                if (actor.boolInstance)
                    {
                    NWN2CreatureInstance inst = (NWN2CreatureInstance)actor.instance;
                    if (inst.FactionID < 0 || inst.FactionID > 12)
                        {
                        inst.FactionID = 2;
                        }
                    }
                else
                    {
                    NWN2CreatureBlueprint blue = (NWN2CreatureBlueprint)actor.blueprint;
                    if (blue.FactionID < 0 || blue.FactionID > 12)
                        {
                        blue.FactionID = 2;
                        }
                    }
                }
            #endregion

            #region getConversationName
            if (actor.Conversation != null && System.IO.Path.GetFileNameWithoutExtension(actor.Conversation.FullName) != String.Empty)
                {
                // I get the name of what the conversation is/should be called
                convName = System.IO.Path.GetFileNameWithoutExtension(actor.Conversation.FullName);
                }
            else if (trigger != null)
                {
                convName = trigger.ToString() + "Conv";
                }
            else
                {
                convName = questNamePrep(questName) + "_" + actor.ToString().Replace(" ", "");
                }
            cConversation = module.Conversations[convName];
            #endregion

            #region ensureConversation
            // If we still have no conversation, then we create one
            if (cConversation == null)
                {
                cConversation = new NWN2GameConversation(convName, module.Repository.DirectoryName, module.Repository);
                cConversation.Demand();
                }
            else
                {
                cConversation.Demand();
                // if we have a conversation, and we have not cleaned it yet - then we do so now, and makes
                // sure that no one else cleans it
                if (alreadyWiped[cConversation.Name] == null)
                    {
                    alreadyWiped[cConversation.Name] = true;

                    NWN2ConversationConnectorCollection connectors = cConversation.StartingList;
                    LinkedList<NWN2ConversationConnector> removeList = new LinkedList<NWN2ConversationConnector>();

                    foreach (NWN2ConversationConnector connnect in connectors)
                        {
                        if (connnect.Comment.Contains("pluginGenerated: " + questName + ":" + questId.ToString()))
                            {
                            removeList.AddLast(connnect);
                            }
                        }

                    debug("Number of convs to remove: " + removeList.Count);
                    foreach (NWN2ConversationConnector removeConnect in removeList)
                        {
                        debug("Removed conversation: " + removeConnect.Text[lang]);
                        cConversation.RemoveNode(removeConnect);
                        }
                    }
                }
            cConversation.OEISerialize(true);
            cConversation.NWN1StyleDialogue = true;
            #endregion
            cConversation = constructConv(cConversation, questName, gender, lang);
            #region FixDoorTalk
            if (actor.type == EnumTypes.actorType.Placeable || actor.type == EnumTypes.actorType.Door)
                {
                NWN2GameScript talkScript = module.Scripts["ga_door_talk"];
                if (talkScript == null)
                    {
                    talkScript = new NWN2GameScript("ga_door_talk", module.Repository.DirectoryName, module.Repository);
                    talkScript.Data = Properties.Resources.ga_door_talk;
                    talkScript.OEISerialize();
                    module.Scripts.Add(talkScript);
                    }
                actor.doorTalk = talkScript.Resource;
                }
            #endregion
            if (triggerHappens != convType.Explore)
                actor.Conversation = cConversation.Resource;
            return cConversation;
        }
Exemple #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dict"></param>
        /// <param name="attachment"></param>
        /// <returns></returns>
        /// <remarks>Note that this automatically opens and closes areas/conversations etc. - it is only
        /// for use with analysis methods, not for users.</remarks>
        public List <ScriptTriggerTuple> GetAllScriptsFromModule(Attachment attachment)
        {
            NWN2GameModule mod = session.GetModule();

            if (mod == null)
            {
                throw new InvalidOperationException("No module is open.");
            }

            NWN2GameScriptDictionary dict = mod.Scripts;

            if (attachment == Attachment.Ignore)
            {
                return(GetTuples(dict));
            }

            Dictionary <Nwn2Address, FlipScript>             moduleScripts       = new Dictionary <Nwn2Address, FlipScript>();
            Dictionary <Nwn2Address, FlipScript>             areaScripts         = new Dictionary <Nwn2Address, FlipScript>();
            Dictionary <Nwn2ConversationAddress, FlipScript> conversationScripts = new Dictionary <Nwn2ConversationAddress, FlipScript>();

            foreach (NWN2GameScript nwn2Script in dict.Values)
            {
                try {
                    nwn2Script.Demand();

                    string code, address, naturalLanguage;
                    ScriptWriter.ParseNWScript(nwn2Script.Data, out code, out address, out naturalLanguage);

                    ScriptType scriptType = GetScriptType(nwn2Script);

                    FlipScript script = new FlipScript(code, scriptType, nwn2Script.Name);

                    Nwn2ConversationAddress ca = Nwn2ConversationAddress.TryCreate(address);
                    if (ca != null)
                    {
                        conversationScripts.Add(ca, script);
                    }

                    else
                    {
                        Nwn2Address a = Nwn2Address.TryCreate(address);

                        if (a != null)
                        {
                            if (a.TargetType == Nwn2Type.Module)
                            {
                                moduleScripts.Add(a, script);
                            }

                            else
                            {
                                areaScripts.Add(a, script);
                            }
                        }
                    }

                    nwn2Script.Release();
                }
                catch (Exception) {}
            }

            List <ScriptTriggerTuple> scripts = new List <ScriptTriggerTuple>(dict.Count);           // this is what we'll return

            if (attachment == Attachment.AttachedToConversation || attachment == Attachment.Attached)
            {
                // Index by conversation name, so we can check all the scripts for a conversation in one go.

                Dictionary <string, List <Nwn2ConversationAddress> > convNameIndex = new Dictionary <string, List <Nwn2ConversationAddress> >();

                foreach (Nwn2ConversationAddress address in conversationScripts.Keys)
                {
                    if (!convNameIndex.ContainsKey(address.Conversation))
                    {
                        convNameIndex.Add(address.Conversation, new List <Nwn2ConversationAddress>());
                    }

                    convNameIndex[address.Conversation].Add(address);
                }

                foreach (string convName in convNameIndex.Keys)
                {
                    NWN2GameConversation conv = mod.Conversations[convName];

                    if (conv == null)
                    {
                        continue;
                    }

                    conv.Demand();

                    foreach (Nwn2ConversationAddress address in convNameIndex[convName])
                    {
                        FlipScript script = conversationScripts[address];

                        NWN2ConversationLine line = conv.GetLineFromGUID(address.LineID);

                        if (line == null)
                        {
                            continue;
                        }

                        if (address.AttachedAs == ScriptType.Standard && line.Actions.Count > 0)
                        {
                            IResourceEntry resource = line.Actions[0].Script;
                            if (resource != null && resource.ResRef.Value == script.Name)
                            {
                                scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                            }
                        }

                        else if (address.AttachedAs == ScriptType.Conditional && line.OwningConnector.Conditions.Count > 0)
                        {
                            IResourceEntry resource = line.OwningConnector.Conditions[0].Script;
                            if (resource != null && resource.ResRef.Value == script.Name)
                            {
                                scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                            }
                        }
                    }

                    conv.Release();
                }
            }

            if (attachment == Attachment.AttachedToScriptSlot || attachment == Attachment.Attached)
            {
                // First, just check for scripts attached to the module - easy:

                foreach (Nwn2Address address in moduleScripts.Keys)
                {
                    FlipScript script = moduleScripts[address];

                    IResourceEntry resource = typeof(NWN2ModuleInformation).GetProperty(address.TargetSlot).GetValue(mod.ModuleInfo, null) as IResourceEntry;

                    if (resource != null && resource.ResRef.Value == script.Name)
                    {
                        scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                    }
                }


                // Next, check whether any script is attached to a Narrative Threads blueprint, and
                // if you find one, add it to the collection and remove it from consideration:

                List <Nwn2Address> processed = new List <Nwn2Address>();

                foreach (Nwn2Address address in areaScripts.Keys)
                {
                    if (Nwn2ScriptSlot.GetObjectType(address.TargetType) == null)
                    {
                        continue;                                                                               // ignore area, module etc.
                    }
                    FlipScript script = areaScripts[address];

                    // First check that if a blueprint which uses this tag as resref exists, it was created by Narrative Threads:
                    if (nt.CreatedByNarrativeThreads(address.TargetType, address.InstanceTag))
                    {
                        NWN2ObjectType objectType = Nwn2ScriptSlot.GetObjectType(address.TargetType).Value;
                        INWN2Blueprint blueprint  = session.GetBlueprint(address.InstanceTag.ToLower(), objectType);

                        if (blueprint != null)
                        {
                            IResourceEntry resource = blueprint.GetType().GetProperty(address.TargetSlot).GetValue(blueprint, null) as IResourceEntry;

                            if (resource != null && resource.ResRef.Value == script.Name)
                            {
                                scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                                processed.Add(address);
                            }
                        }
                    }
                }

                foreach (Nwn2Address p in processed)
                {
                    areaScripts.Remove(p);                                                  // has been added, so don't check for it more than once
                }
                // Then, open each area in turn, and see whether a script is attached to it. If it is, add
                // it to the collection and remove it from consideration:

                foreach (NWN2GameArea area in mod.Areas.Values)
                {
                    if (areaScripts.Count == 0)
                    {
                        break;
                    }

                    session.OpenArea(area);

                    processed = new List <Nwn2Address>();

                    foreach (Nwn2Address address in areaScripts.Keys)
                    {
                        FlipScript script = areaScripts[address];

                        if (address.TargetType == Nwn2Type.Area)
                        {
                            IResourceEntry resource = typeof(NWN2GameArea).GetProperty(address.TargetSlot).GetValue(area, null) as IResourceEntry;

                            if (resource != null && resource.ResRef.Value == script.Name)
                            {
                                scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                                processed.Add(address);                                 // don't check whether to add it more than once
                            }
                        }

                        else
                        {
                            NWN2InstanceCollection instances = session.GetObjectsByAddressInArea(address, area.Tag);

                            if (instances != null)
                            {
                                // Check the script is still attached to the target object in the slot it claims to be,
                                // in at least one instance, and if so add it to the set of scripts to be opened:

                                foreach (INWN2Instance instance in instances)
                                {
                                    IResourceEntry resource = instance.GetType().GetProperty(address.TargetSlot).GetValue(instance, null) as IResourceEntry;

                                    if (resource != null && resource.ResRef.Value == script.Name)
                                    {
                                        scripts.Add(new ScriptTriggerTuple(script, triggerFactory.GetTriggerFromAddress(address)));
                                        processed.Add(address);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    foreach (Nwn2Address p in processed)
                    {
                        areaScripts.Remove(p);                                                      // has been added, so don't check for it more than once
                    }
                    session.CloseArea(area);
                }
            }

            return(scripts);
        }