[Release] Xml Npcs

04/04/2010 15:41 kinshi88#1
Honestly, was just bored so I thought I'd take a look at C# since I haven't for a few months.

Hard-coded Npc's suck balls, so here's the starting code for Xml Npc's.

Pretty sure it was done within CoEmu v2, but can easily be converted into any source.

I haven't tested it, since I don't have a Conquer client.

Instructions:

- Includes:
Code:
using System.Xml;
Code:
using System.IO;
- Add the following to (pretty much) the top of the NpcTalk function in NpcTalk.cs (before the switch(ID)):
--- Don't forget to comment out the hard-coded npc's;
Code:
            if (!File.Exists("npc/" + ID + ".xml"))
                return;
            XmlTextReader npcXml = new XmlTextReader("npc/" + ID + ".xml");

            string type = "";
            int lb = 0, current = 0;

            string arg, val, sign;
            arg = val = sign = null;

            while (npcXml.Read())
            {
                switch (npcXml.NodeType)
                {
                    case XmlNodeType.Element:
                        type = npcXml.Name;
                        switch (type)
                        {
                            case "instance":
                                current = Convert.ToInt32(npcXml.GetAttribute("id"));
                                break;
                            case "if":
                                if (current != LinkBack)
                                    break;
                                arg = npcXml.GetAttribute("arg");
                                val = npcXml.GetAttribute("val");
                                sign = npcXml.GetAttribute("sign");
                                break;
                        }
                        break;
                    case XmlNodeType.Text:
                        npcXml.Value.Trim();
                        if (current != LinkBack)
                            continue;
                        if (!checkArgs(arg, val, sign, CSocket))
                            continue;
                        switch (type)
                        {
                            case "text":
                                string s = npcXml.Value;
                                s = s.Replace("@name", CSocket.Client.Name);
                                s = s.Replace("@level", CSocket.Client.Level.ToString());
                                Text(s, CSocket);
                                break;
                            case "link":
                                lb = Convert.ToInt32(npcXml.GetAttribute("lb"));
                                Link(npcXml.Value, lb, CSocket);
                                break;
                            case "input":
                                lb = Convert.ToInt32(npcXml.GetAttribute("lb"));
                                Input(npcXml.Value, lb, CSocket);
                                break;
                        }
                        break;
                    case XmlNodeType.EndElement:
                        if (current != LinkBack)
                            continue;
                        switch (npcXml.Name)
                        {
                            case "instance":
                                End(CSocket);
                                break;
                            case "if":
                                arg = val = sign = null;
                                break;
                        }
                        break;
                }
            }
- Add this to the bottom of NpcTalk.cs, same place as the Text function etc:
Code:
        static bool checkArgs(string arg, string val, string sign, ClientSocket CSocket)
        {
            if (arg == null || val == null) return true;
           
            object lhs = new object();
            object rhs = new object();
            switch (arg)
            {
                case "reborn":
                    lhs = CSocket.Client.Reborn;
                    rhs = Convert.ToInt32(val);
                    break;
                case "level":
                    lhs = CSocket.Client.Level;
                    rhs = Convert.ToInt32(val);
                    break;
                case "inventorycount":
                    lhs = CSocket.Client.Inventory.Count;
                    rhs = Convert.ToInt32(val);
                    break;
                case "inventorycontains":
                    if (Calculation.InventoryContains(
                        Convert.ToInt32(val), 
                        Convert.ToInt32(sign), CSocket))
                        return true;
                    else return false;
            }
            switch (sign)
            {
                case "equal":
                    if (Convert.ToInt64(lhs.ToString()) ==
                        Convert.ToInt64(rhs.ToString())) return true;
                    else return false;
                case "greatequal":
                    if (Convert.ToInt64(lhs.ToString()) >=
                        Convert.ToInt64(rhs.ToString())) return true;
                    else return false;
                case "lessequal":
                    if (Convert.ToInt64(lhs.ToString()) <=
                        Convert.ToInt64(rhs.ToString())) return true;
                    else return false;
                case "great":
                    if (Convert.ToInt64(lhs.ToString()) >
                        Convert.ToInt64(rhs.ToString())) return true;
                    else return false;
                case "less":
                    if (Convert.ToInt64(lhs.ToString()) <
                        Convert.ToInt64(rhs.ToString())) return true;
                    else return false;
            }
            return false;
        }
- Xml file example:
--- id is the equivalent to LinkBack
--- lb is the id to go to when the link is clicked
--- if works like a normal if statement:
------- args is what to check
------- sign (great is >, equal is ==)
------- val is what to compare
------- In the case of inventorycontains, sign is how many the inventory contains
Code:
<npc>
	<instance id='0'>
		<text>What up @name?</text>
		<if arg='level' sign='greatequal' val='100'>
			<text>At least level 100!</text>
		</if>
		<link lb='1'>Not much</link>
		<input lb='2'>Amount:</input>
	</instance>
	
	<instance id='1'>
		<text>Cool Cool</text>
		<if arg='reborn' sign='equal' val='0'>
			<link lb='3'>Not reborn</link>
		</if>
		<if arg='reborn' sign='great' val='0'>
			<link lb='3'>Reborn at least once</link>
			<link lb='3'>Good job</link>
		</if>
	</instance>
	
	<instance id='2'>
		<if arg='inventorycontains' sign='1' val='721259'>
			<text>You have it!</text>
		</if>
		
		<if arg='inventorycount' sign="lessequal" val='30'>
			<text>Inventory Count test!</text>
		</if>
	</instance>
</npc>
You can add more for special checks and functions, I'll help if anyone has requests for more.

Enjoy! =D



If you're interested in using this, I can add more functions over time.
04/04/2010 16:01 hunterman01#2
Xml is hard : /
04/04/2010 16:31 KraHen#3
Quote:
Originally Posted by hunterman01 View Post
Xml is hard : /
Easier to work with than INI IMO...
04/04/2010 17:19 kinshi88#4
Quote:
Originally Posted by hunterman01 View Post
Xml is hard : /
Its a markup language, like Html. They're like exactly the same pretty much =P

Quote:
Originally Posted by ElDeRnEcRo View Post
Easier to work with than INI IMO...
Ooohhhh yeah =P
04/04/2010 17:28 ~Yuki~#5
LUA is easier too ^^
04/04/2010 17:34 kinshi88#6
Quote:
Originally Posted by ~Yuki~ View Post
LUA is easier too ^^
Yeah Lua is hardcore
04/04/2010 19:38 QuickCo#7
good work