Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Myran

Pages: 1 [2] 3 4 ... 13
16
Technical Support / Re: Visual C++ Error
« on: February 01, 2015, 03:37:17 AM »
Okay, so that log looks pretty good. Have you tried downloading this dll http://www.hammerwatch.com/OpenAL32.dll and putting it in the game directory? It doesn't look sound related from the log, but it could be.

17
Technical Support / Re: Black screen,only hear music[PLS HELP :3]
« on: February 01, 2015, 03:34:07 AM »
Um, you get no error message or crash? You could try reinstalling the game (make sure you backup your save files, they are in the game directory). I have never had a report of this error before, so unless you have changed your hardware it kinda seems like the installation has been broken somehow. Try doing the verify integrity of game cache in Steam.

18
Technical Support / Re: Game is Still crashing before it even starts
« on: February 01, 2015, 03:32:15 AM »
You seem to have resources from an older version of the game being loaded in to a new version. This could be your assets.bin that could be corrupted or not updated, or maybe you previously extracted it in to an assets folder? In that case you should probably delete the folder.

19
Technical Support / Re: Weirdness involved here please help.
« on: January 11, 2015, 02:21:37 AM »
What graphics card do you have?

20
Technical Support / Re: Visual C++ Error
« on: January 11, 2015, 02:20:59 AM »
Do you get an error file or a game log file in your game directory? If so please attach it here so I can take a look.

21
You will be able to teleport independently, yes. The local co-op will be split-screen instead of the shared screen like in Hammerwatch so that we can split up players.
We've been thinking about being able to be on different levels and we're not sure yet if it will be possible. There are some interesting technical and logical challenges to supporting that, so it's something that might just be too much work, but at least we want it and we haven't excluded it yet.


Yes, it should be possible to make a MOBA, although it will probably require you to write quite a bit of code to make it really nice (like, at least some custom skills and custom AI for the creeps)

22
So a big reason why I'm rewriting the engine from scratch is to get a much more robust system for modding. The plan is for pretty much anything game-specific to be done in scripts, and all those scripts should be possible to modify. We don't yet have the script system in the editor that we had in Hammerwatch, but when we do I plan to implement all the script nodes as modifiable code.


Since I've mostly worked on the engine I don't have a lot of scripts to show, but as an example here is a hit-scan skill used both by player weapons and by some of our enemies:
Code: [Select]
class Hitscan : IAction
{
array<IEffect@>@ m_effects;

int m_rays;

int m_rangeMin;
int m_rangeMax;

float m_spread;
float m_spreadMin;
float m_spreadMax;
int m_spreadTime;
int m_spreadTimeC;
int m_spreadCooldown;

string m_shootFx;
string m_hitFx;
string m_missFx;


Hitscan(SValue& params)
{
@m_effects = LoadEffects(this, params);
m_rays = GetParami(this, params, "rays", false, 1);

SValue@ spread = GetParamd(this, params, "spread", false);
if (spread !is null)
{
m_spreadMin = GetParami(this, spread, "min") * PI / 180.0;
m_spreadMax = GetParami(this, spread, "max") * PI / 180.0;
m_spreadTime = GetParami(this, spread, "time");
m_spreadCooldown = GetParami(this, params, "cooldown", false, 100);
}
else
m_spread = GetParami(this, params, "spread", false) * PI / 180.0;

SValue@ range = GetParamd(this, params, "range", false);
if (range !is null)
{
m_rangeMin = GetParami(this, range, "min");
m_rangeMax = GetParami(this, range, "max");
}
else
{
m_rangeMin = GetParami(this, params, "range");
m_rangeMax = -1;
}

m_shootFx = GetParams(this, params, "shoot-fx", false);
m_hitFx = GetParams(this, params, "hit-fx", false);
m_missFx = GetParams(this, params, "miss-fx", false);
}

bool DoAction(Actor@ owner, vec2 pos, vec2 dir)
{
if (m_spreadTime > 0)
{
m_spread = lerp(m_spreadMin, m_spreadMax, min(1.0, m_spreadTimeC / float(m_spreadTime)));
m_spreadTimeC = min(m_spreadTime, m_spreadTimeC + m_spreadCooldown);
}

if (m_shootFx != "")
PlayEffect(m_shootFx, pos);

dir = normalize(dir);

for (int i = 0; i < m_rays; i++)
{
vec2 shootPos = dir;
if (m_spread > 0)
{
float ang = atan(shootPos.y, shootPos.x) + (randf() - 0.5) * m_spread;
shootPos = vec2(cos(ang), sin(ang));
}

if (m_rangeMin < m_rangeMax)
shootPos *= m_rangeMin + randi(m_rangeMax - m_rangeMin);
else
{
shootPos *= m_rangeMin;
}

shootPos += pos;

RaycastResult res = g_scene.RaycastClosest(pos, shootPos, ~0);
if (res.unit !is null)
{
Actor@ a = cast<Actor>(res.unit.GetScriptBehavior());
if (a !is null && a.Team != owner.Team)
ApplyEffects(m_effects, owner, a, xy(a.m_unit.GetPosition()), dir, 1.0);

if (m_hitFx != "")
PlayEffect(m_hitFx, res.point);
}
else if (m_missFx != "")
PlayEffect(m_missFx, shootPos);
}
return true;
}

void Update(int dt, int cooldown)
{
if (cooldown <= 0)
m_spreadTimeC = 0;
}
}

And here is how we use it in our enemy unit file xmls:
Code: [Select]
<array name="actions">
<dict>
<string name="class">Hitscan</string>

<int name="range">175</int>
<int name="rays">10</int>

<dict name="effect">
<string name="class">Damage</string>
<int name="dmg">8</int>
</dict>

<dict name="spread">
<int name="min">25</int>
<int name="max">50</int>
<int name="time">3000</int>
</dict>


<string name="hit-fx">units/hit_smoke.unit</string>
<string name="miss-fx">units/miss_smoke.unit</string>
</dict>
</array>

It's still early in the development, so this will of course change, but that's what we have right now.



I'm stuck in the menu, the music plays full speed but the graphic output is lagging and has a terrible frame-rate (probably 1 frame per 20 seconds.) Any suggestions? It ran fine when I first got it, and I already re-installed it to see if that would fix any problems. Unfortunately, it did not.
Have you tried turning off the steam overlay in Hammerwatch? It has caused problems for some people on Mac. And have you updated your graphics drivers?

23
Hammerwatch used to use the full OpenTK library, but when we switched to SDL2# we no longer need to use the dll. And yeah, shouldn't be a problem to just include the Vector2 class.

24
Cool project! :) I don't really know much about AutoHotkey, but if you want the saves in XML format here is the C# class that the game and editor uses for the binary and XML serialization of data, just load the save file with LoadStream() and then save the result with SaveXML(), the format isn't complicated so you can maybe use it to write your own in AutoHotkey.

Code: [Select]
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using OpenTK;

namespace TiltedEngine
{
    public enum SValueType
    {
        Array,
        Object,
        Boolean,
        Double,
        Float,
        Integer,
        String,
        IntegerArray,
        Vector2,
        Null
    }

   
    public class SValue
    {
        public SValueType Type;
        private object value;

        public SValue()
        {
            Type = SValueType.Null;
            value = null;
        }

        public SValue(SValue[] v)
        {
            Type = SValueType.Array;
            value = v;
        }

        public SValue(SObject v)
        {
            Type = SValueType.Object;
            value = v;
        }

        public SValue(bool v)
        {
            Type = SValueType.Boolean;
            value = v;
        }

        public SValue(double v)
        {
            Type = SValueType.Double;
            value = v;
        }

        public SValue(float v)
        {
            Type = SValueType.Float;
            value = v;
        }

        public SValue(int v)
        {
            Type = SValueType.Integer;
            value = v;
        }

        public SValue(string v)
        {
            Type = SValueType.String;
            value = v;
        }

        public SValue(int[] v)
        {
            Type = SValueType.IntegerArray;
            value = v;
        }

        public SValue(Vector2 v)
        {
            Type = SValueType.Vector2;
            value = v;
        }

        public SValue(float x, float y)
        {
            Type = SValueType.Vector2;
            value = new Vector2(x, y);
        }

        public SValue(object v, SValueType type)
        {
            Type = type;
            value = v;
        }



        public SValue[] GetArray() { return (SValue[])value; }
        public SObject GetObject() { return (SObject)value; }
        public bool GetBoolean() { return (bool)value; }
        public double GetDouble() { return (double)value; }
        public float GetFloat() { return (float)value; }
        public int GetInteger() { return (int)value; }
        public string GetString() { return (string)value; }
        public int[] GetIntegerArray() { return (int[])value; }
        public Vector2 GetVector2() { return (Vector2)value; }

        public object GetRawValue() { return value; }

       
        public static implicit operator SValue(SValue[] val) { return new SValue(val); }
        public static implicit operator SValue(SObject val) { return new SValue(val); }
        public static implicit operator SValue(bool val) { return new SValue(val); }
        public static implicit operator SValue(double val) { return new SValue(val); }
        public static implicit operator SValue(float val) { return new SValue(val); }
        public static implicit operator SValue(int val) { return new SValue(val); }
        public static implicit operator SValue(string val) { return new SValue(val); }
        public static implicit operator SValue(int[] val) { return new SValue(val); }
        public static implicit operator SValue(Vector2 val) { return new SValue(val); }

        public static SValue FromArray(SValue[] val) { return new SValue(val, SValueType.Array); }
        public static SValue FromObject(SObject val) { return new SValue(val, SValueType.Object); }
        public static SValue FromBoolean(bool val) { return new SValue(val, SValueType.Boolean); }
        public static SValue FromDouble(double val) { return new SValue(val, SValueType.Double); }
        public static SValue FromFloat(float val) { return new SValue(val, SValueType.Float); }
        public static SValue FromInteger(int val) { return new SValue(val, SValueType.Integer); }
        public static SValue FromString(string val) { return new SValue(val, SValueType.String); }
        public static SValue FromIntegerArray(int[] val) { return new SValue(val, SValueType.IntegerArray); }
        public static SValue FromVector2(Vector2 val) { return new SValue(val, SValueType.Vector2); }

        public bool IsNull()
        {
            return Type == SValueType.Null;
        }

        public static SValue FromXMLFile(TextReader xml)
        {
            var doc = XDocument.Load(xml);
            return ParseXMLNode(doc.Root);
        }

        public static SValue FromXMLString(string xml)
        {
            var doc = XDocument.Parse(xml);
            return ParseXMLNode(doc.Root);
        }

        public static SValue FromXMLDocument(XElement xml)
        {
            return ParseXMLNode(xml);
        }

        private static SValue ParseXMLNode(XElement node)
        {
            switch (node.Name.LocalName)
            {
                case "array":
                    var arr = new List<SValue>();
                    foreach (var child in node.Elements())
                        arr.Add(ParseXMLNode(child));

                    return FromArray(arr.ToArray());

                case "dictionary":
                    var dict = new SObject();
                    foreach (var child in node.Elements())
                    {
                        var name = child.Attribute("name").Value;
                        if (child.Name == "entry")
                            dict.Set(name, ParseXMLNode(child.Elements().First()));
                        else
                            dict.Set(name, ParseXMLNode(child));
                    }
                    return FromObject(dict);

                case "bool":
                    return FromBoolean(bool.Parse(node.Value));
                case "double":
                    return FromDouble(double.Parse(node.Value, CultureInfo.InvariantCulture));
                case "float":
                    return FromFloat(float.Parse(node.Value, CultureInfo.InvariantCulture));
                case "int":
                    return FromInteger(int.Parse(node.Value, CultureInfo.InvariantCulture));
                case "string":
                    return FromString(node.Value);
                case "vec2":
                    {
                        var sarr = node.Value.Split(' ');
                        return FromVector2(new Vector2(float.Parse(sarr[0], CultureInfo.InvariantCulture), float.Parse(sarr[1], CultureInfo.InvariantCulture)));
                    }

                case "int-arr":
                    {
                        var sarr = node.Value.Split(' ');
                        var iarr = new int[sarr.Length];

                        for (var j = 0; j < sarr.Length; j++)
                            iarr[j] = int.Parse(sarr[j], CultureInfo.InvariantCulture);

                        return FromIntegerArray(iarr);
                    }
            }

            return new SValue(null, SValueType.Null);
        }

        public static void SaveXML(SValue val, TextWriter tw, string indent = "", string name = null, bool compact = false)
        {
            if (!compact)
                tw.Write(indent);

            switch (val.Type)
            {
                case SValueType.Array:
                    {
                        var arr = val.GetArray();
                        var childCompact = compact;
                        if (arr.Length < 10 && !childCompact)
                        {
                            childCompact = true;
                            foreach (var arrEntry in arr)
                                if (arrEntry.Type == SValueType.Object || arrEntry.Type == SValueType.IntegerArray || arrEntry.Type == SValueType.Array)
                                {
                                    childCompact = false;
                                    break;
                                }
                        }

                        tw.Write(name == null ? "<array>" : "<array name=\"" + name + "\">");

                        if (!childCompact)
                            tw.WriteLine();

                       
                        foreach (var arrEntry in arr)
                            SaveXML(arrEntry, tw, indent + "\t", null, childCompact);

                        if (!childCompact)
                            tw.Write(indent);

                        tw.Write("</array>");
                    }
                    break;

                case SValueType.Object:
                    {
                        tw.WriteLine(name == null ? "<dictionary>" : "<dictionary name=\"" + name + "\">");

                        var dict = val.GetObject();
                        foreach (var dictEntry in dict)
                            SaveXML(dictEntry.Value, tw, indent + "\t", dictEntry.Key, compact);

                        if (!compact)
                            tw.Write(indent);

                        tw.Write("</dictionary>");
                    }
                    break;

                case SValueType.Boolean:
                    tw.Write(name == null ? "<bool>" : "<bool name=\"" + name + "\">");
                    tw.Write(val.GetBoolean() + "</bool>");
                    break;
                case SValueType.Double:
                    tw.Write(name == null ? "<double>" : "<double name=\"" + name + "\">");
                    tw.Write(val.GetDouble().ToString(CultureInfo.InvariantCulture) + "</double>");
                    break;
                case SValueType.Float:
                    tw.Write(name == null ? "<float>" : "<float name=\"" + name + "\">");
                    tw.Write(val.GetFloat().ToString(CultureInfo.InvariantCulture) + "</float>");
                    break;
                case SValueType.Integer:
                    tw.Write(name == null ? "<int>" : "<int name=\"" + name + "\">");
                    tw.Write(val.GetInteger() + "</int>");
                    break;
                case SValueType.String:
                    tw.Write(name == null ? "<string>" : "<string name=\"" + name + "\">");
                    tw.Write(val.GetString() + "</string>");
                    break;

                case SValueType.Vector2:
                    tw.Write(name == null ? "<vec2>" : "<vec2 name=\"" + name + "\">");
                    var v2 = val.GetVector2();
                    tw.Write(v2.X.ToString(CultureInfo.InvariantCulture));
                    tw.Write(" ");
                    tw.Write(v2.Y.ToString(CultureInfo.InvariantCulture));
                    tw.Write("</vec2>");
                    break;

                case SValueType.IntegerArray:
                    tw.Write(name == null ? "<int-arr>" : "<int-arr name=\"" + name + "\">");

                    var v = val.GetIntegerArray();
                    for (var i = 0; i < v.Length; i++)
                    {
                        tw.Write(v[i]);
                        if (i != v.Length - 1)
                            tw.Write(' ');
                    }
                    tw.Write("</int-arr>");
                    break;

                case SValueType.Null:
                    tw.Write(name == null ? "<null/>" : "<null name=\"" + name + "\"/>");
                    break;
            }

            if (!compact)
                tw.WriteLine();
        }




        public static SValue FindDictionaryEntry(BinaryReader sr, string name)
        {
            var type = sr.ReadByte();
            switch (type)
            {
                case 1:
                    {
                        var len = sr.ReadInt32();
                        for (var j = 0; j < len; j++)
                        {
                            var ret = FindDictionaryEntry(sr, name);
                            if (ret != null)
                                return ret;
                        }

                        return null;
                    }
                case 2:
                    {
                        var len = sr.ReadInt32();
                        for (var j = 0; j < len; j++)
                        {
                            var nm = sr.ReadString();
                            if (nm == name)
                                return LoadStream(sr);

                            var ret = FindDictionaryEntry(sr, name);
                            if (ret != null)
                                return ret;
                        }

                        return null;
                    }

                case 3:
                    sr.BaseStream.Seek(1, SeekOrigin.Current);
                    return null;
                case 4:
                    sr.BaseStream.Seek(8, SeekOrigin.Current);
                    return null;
                case 5:
                    sr.BaseStream.Seek(4, SeekOrigin.Current);
                    return null;
                case 6:
                    sr.BaseStream.Seek(4, SeekOrigin.Current);
                    return null;
                case 7:
                    sr.ReadString();
                    return null;

                case 8:
                    {
                        var len = sr.ReadInt32();
                        sr.BaseStream.Seek(4 * len, SeekOrigin.Current);
                        return null;
                    }

                case 9:
                    sr.BaseStream.Seek(4 * 2, SeekOrigin.Current);
                    return null;
            }

            return null;
        }


        public static SValue LoadStream(BinaryReader sr)
        {
            var type = sr.ReadByte();
            switch (type)
            {
                case 1:
                    {
                        var len = sr.ReadInt32();

                        var arr = new SValue[len];
                        for (var j = 0; j < arr.Length; j++)
                            arr[j] = LoadStream(sr);

                        return FromArray(arr.ToArray());
                    }
                case 2:
                    {
                        var len = sr.ReadInt32();

                        var dict = new SObject();
                        for (var j = 0; j < len; j++)
                        {
                            var name = sr.ReadString();
                            dict.Set(name, LoadStream(sr));
                        }
                        return FromObject(dict);
                    }

                case 3:
                    return FromBoolean(sr.ReadBoolean());
                case 4:
                    return FromDouble(sr.ReadDouble());
                case 5:
                    return FromFloat(sr.ReadSingle());
                case 6:
                    return FromInteger(sr.ReadInt32());
                case 7:
                    return FromString(sr.ReadString());

                case 8:
                    {
                        var len = sr.ReadInt32();
                       
                        var iarr = new int[len];
                        for (var j = 0; j < iarr.Length; j++)
                            iarr[j] = sr.ReadInt32();

                        return FromIntegerArray(iarr);
                    }

                case 9:
                    return FromVector2(new Vector2(sr.ReadSingle(), sr.ReadSingle()));
            }

            return new SValue(null, SValueType.Null);
        }



        public static void SaveStream(SValue val, BinaryWriter sw)
        {
            switch (val.Type)
            {
                case SValueType.Array:
                    {
                        sw.Write((byte)1);

                        var arr = val.GetArray();
                        sw.Write(arr.Length);

                        foreach (var arrEntry in arr)
                            SaveStream(arrEntry, sw);
                    }
                    break;

                case SValueType.Object:
                    {
                        sw.Write((byte)2);

                        var dict = val.GetObject();
                        sw.Write(dict.Size);

                        foreach (var dictEntry in dict)
                        {
                            sw.Write(dictEntry.Key);
                            SaveStream(dictEntry.Value, sw);
                        }
                    }
                    break;

                case SValueType.Boolean:
                    sw.Write((byte)3);
                    sw.Write(val.GetBoolean());
                    break;
                case SValueType.Double:
                    sw.Write((byte)4);
                    sw.Write(val.GetDouble());
                    break;
                case SValueType.Float:
                    sw.Write((byte)5);
                    sw.Write(val.GetFloat());
                    break;
                case SValueType.Integer:
                    sw.Write((byte)6);
                    sw.Write(val.GetInteger());
                    break;
                case SValueType.String:
                    sw.Write((byte)7);
                    sw.Write(val.GetString() ?? "");
                    break;

                case SValueType.IntegerArray:
                    sw.Write((byte)8);

                    var iArr = val.GetIntegerArray();
                    sw.Write(iArr.Length);

                    for (var i = 0; i < iArr.Length; i++)
                        sw.Write(iArr[i]);

                    break;

                case SValueType.Vector2:
                    sw.Write((byte)9);
                    var v2 = val.GetVector2();
                    sw.Write(v2.X);
                    sw.Write(v2.Y);
                    break;

                case SValueType.Null:
                    sw.Write((byte)0);
                    break;
            }
        }
    }



    public class SObject : IEnumerable<KeyValuePair<string, SValue>>
    {
        Dictionary<string, SValue> values;

        public SObject()
        {
            values = new Dictionary<string, SValue>();
        }

        public SValue this[string index]
        {
            get
            {
                SValue val;
                if (values.TryGetValue(index, out val))
                    return val;

                return new SValue();
            }
            set
            {
                values[index] = value;
            }
        }

        public SValue Get(string index)
        {
            SValue val;
            if (values.TryGetValue(index, out val))
                return val;

            return new SValue(null, SValueType.Null);
        }

        public void Set(string index, SValue value)
        {
            values[index] = value;
        }


        public int Size { get { return values.Count; } }

        public IEnumerator<KeyValuePair<string, SValue>> GetEnumerator()
        {
            return values.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

25
Technical Support / Re: Map bug?
« on: October 12, 2014, 05:36:19 PM »
Oh wow..  I've never tried with a map that big, but if the LevelPacker accepted it, then the game should also. Hm, can you try removing some of those sounds to get down the size and see if that helps?

26
What graphics card do you have? And have you tried updating your graphics drivers?

27
Technical Support / Re: My Hammerwatch don't work HELP ME !!!!!
« on: October 12, 2014, 05:34:39 PM »
OpenGL 1.4? Have you tried updating your graphics drivers?

28
Would it be possible to add a preference where I can spawn a new object of a type I have selected on the actual map window? Like if I'm putting down walls and decide I want to add some torches, I could just click on an existing torch on the map and right click to create a new torch, instead of having to go back and look up the torch object.
If you hold ALT and click an object it will work like a color picker and select that object from the list.

29
Editor Discussion / Re: How to End a Campaing
« on: September 15, 2014, 12:24:34 AM »
The end screen shows when you trigger the "GameEnd" script node.

30
The LevelPacker expects a path to a folder containing at least two files, a info.xml and a levels.xml. If you only have a single xml for your level you still need those two for additional metadata about your campaign (stuff like name and description of it). You can just copy them from the editor/example folder and edit those.

Pages: 1 [2] 3 4 ... 13