• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

SharpCraft, a managed replacement for Reinventing the Craft

Status
Not open for further replies.
Level 4
Joined
May 25, 2009
Messages
100
You're right, but I meant the Sharpcraft specific natives.
Will it be possible in the future? I would love to play a 3rd person mmo with sharpcraft and warcom :D
 
Level 5
Joined
Nov 10, 2009
Messages
85
Hello im having a problem using the multiplayer emulation with sharpcraft... keeps telling me "unable to initialize Warcraft III" after attempting to open more than one window at a time... it will open the first but not the rest...
 
Hello im having a problem using the multiplayer emulation with sharpcraft... keeps telling me "unable to initialize Warcraft III" after attempting to open more than one window at a time... it will open the first but not the rest...

Well: (1) the multiplayer emulation feature won't hook SharpCraft (2) it is likely an issue related to JNGP/kloader rather than SharpCraft.

You should make the post here:
http://www.hiveworkshop.com/forums/...x-beta-recruiting-testing-233145/index25.html

:)
 
Level 4
Joined
May 25, 2009
Messages
100
As far as i know it's not possible. For example:
I register a LMB click - event with TriggerRegisterMouseEvent() and add an action. Now the code gets fire everytime a player clicks the LMB and the action gets called.
But then the function doesn't know which player pressed the button.
Because TriggerRegisterMouseEvent() isn't a Wc3 native, i can't catch the GetTriggerPlayer(), so GetLocalPlayer() == GetTriggerPlayer() doesn't work and GetLocalPlayer() == Player(0) gets called, even if Player 2 pressed the LMB (Just for Player 1 but i still don't want that).

And by the way: Is it even possible right now, to have more than 1 human player? Because there're no playerslot in the lobby for sharpcraftmaps.
 
As far as i know it's not possible. For example:
I register a LMB click - event with TriggerRegisterMouseEvent() and add an action. Now the code gets fire everytime a player clicks the LMB and the action gets called.
But then the function doesn't know which player pressed the button.
Because TriggerRegisterMouseEvent() isn't a Wc3 native, i can't catch the GetTriggerPlayer(), so GetLocalPlayer() == GetTriggerPlayer() doesn't work and GetLocalPlayer() == Player(0) gets called, even if Player 2 pressed the LMB (Just for Player 1 but i still don't want that).

I think Bribe's post is correct about it. At least, I remember it behaving that way with RtC. As such, you can just do SetCameraField() and modify the camera as needed (it works fine locally).

And by the way: Is it even possible right now, to have more than 1 human player? Because there're no playerslot in the lobby for sharpcraftmaps.

Well, it is possible in some cases. When maps are loaded in the lobby, wc3 does a quick syntax check. If it fails, it won't show the player slots. So when you use custom natives, it will fail to show the player slots. edit: I am not sure whether that last statement is entirely true or not, I suppose you'll have to wait for a response from MindWorX.

However, SharpCraft can also let you modify existing natives. For example, in the demo map attached in the main post, it modifies the behavior of Cheat("") with particular string input. As such, it will load in regular wc3 (so you can host it just fine), but it won't do anything unless you have SharpCraft. That may seem useless, but it'll allow the map to be hosted on BNet, so the users with SharpCraft can play it in multiplayer. I imagine you can do something similar to fit your needs.

Otherwise, you can wait for WarCom: http://www.hiveworkshop.com/forums/lab-715/warcom-multiplayer-mod-increase-player-limit-243313/
 
Last edited:
Level 1
Joined
Sep 14, 2010
Messages
8
I did what you said. I came to the point where it opens Warcraft, then it (the "console") crashes (stops working). And I am still unable to start the Sharpcraft map.
Thanks for taking your time to help!
 
I did what you said. I came to the point where it opens Warcraft, then it (the "console") crashes (stops working). And I am still unable to start the Sharpcraft map.
Thanks for taking your time to help!

Run Sharpcraft.Game.exe -window with pause.bat and see what the console shows. Take a screenshot if possible (print screen, ctrl + c, ctrl + v into any image editor e.g. paint, save as jpg and upload).
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Level 8
Joined
Feb 3, 2013
Messages
277
mhppo1.png


this is what i get -_- in 2.07
 
Level 1
Joined
Sep 14, 2010
Messages
8
Here it is, this is how it looks when it crashes. It starts Wc3 but only the main menu.
 

Attachments

  • Sharp.JPG
    Sharp.JPG
    28.7 KB · Views: 163

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
mhppo1.png


this is what i get -_- in 2.07
Looks like an issue with the registry database. Not sure exactly what though. Try and make sure everything is in order in the registry.
Here it is, this is how it looks when it crashes. It starts Wc3 but only the main menu.
Seems like it's failing injecting the hack. I've been improving the injection technique, so the next version might work better. :)
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You know what, we should honestly just use SharpCraft for b.net, heh. We can use WarCom too. Combo never hurt anyone.

I mean, this works on b.net. You have 0 chance of getting banned for using this. Might as well >.>. It beats JASS anyhow. The recent benchmarks I did analyzing actual times it takes to run JASS code are kind of demoralizing.
 
Level 4
Joined
May 25, 2009
Messages
100
What about adding the System.Drawing to the reference, so we could paint some images on the screen? :D
Or is there an issue i don't know about?
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Can you make wc3 reload some files on map init it currently only does on game startup, so we can have custom soundsets for example?
I really doubt that's going to be doable, but I'll keep in in the back of my head. :)

What about adding the System.Drawing to the reference, so we could paint some images on the screen? :D
Or is there an issue i don't know about?
It's not quite that simple, but I have hooked DirectX which allows drawing on screen. Not much work has been put into it yet though.
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
New release!

Changelog
Code:
v2.2.4
 * Giant refactor. Too many changes to list them all.
 * Added three new base classes for scripting.
 * * FullPluginBase; // This class is for plugins that need full access, which means file writing and more.
 * * SafePluginBase; // This class is for plugins that only need safe access.
 * * MapScriptBase;  // This class is for internal war3map.cs scripts. It is similar to SafePluginBase.
 * The sandbox milestone reached 100%, meaning more safety.
 * Interplugin usage it possible through simple dependency.
 
Last edited:
Level 4
Joined
May 25, 2009
Messages
100
I'm feeling like sb showed me a room full with awesome stuff....but i have no idea how to open the door^^
Will there be some tutorials or example plugins so sb. who isn't deep into c# can write a little plugin without looking through the whole sourcecode and trying to understand it? :D
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Code:
sub_6F2F45D0Hook
 - this: 1BEF0088
 - id: A000
 - order: healon
 - uberTip: "H|cffffcc00e|ral"(16)
 - tooltip: "Heals a target friendly non-mechanical wounded unit for 101 hit points. Costs 801 mana.

|cffc3dbffRight-click to activate auto-casting.|r"(138)
 - a5: 00000321
 - result: 0000008A
Another teaser for the tech savvy people...
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
C#:
...
    private void Script_PostMain()
    {
        var trigger = JassTrigger.Create();
        trigger.RegisterPlayerEvent(JassPlayer.FromIndex(0), JassPlayerEvent.EndCinematic);
        trigger.AddAction(new Action(this.ESCAction));
    }

    private void ESCAction()
    {
        Trace.WriteLine("ESC");
    }
...
Another teaser for a long requested feature...
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Ehm, I'm a little bit confused - what kind of feature? Or is it the ability to write script for maps in C#?

Scripting using C# is possible. However, it had a limitation. You couldn't detect JASS events, like unit death, units entering regions, etc. But the teaser shows that it's now possible. Still need to fix a few issues, but it's getting better.
 
Level 4
Joined
May 25, 2009
Messages
100
Does it still have the Jass Limitations, eg. adding parameters to the action calls?

JASS:
...
    private void Script_PostMain()
    {
        string s = "ESC"
        var trigger = JassTrigger.Create();
        trigger.RegisterPlayerEvent(JassPlayer.FromIndex(0), JassPlayerEvent.EndCinematic);
        trigger.AddAction(new Action(this.ESCAction(s)));
    }

    private void ESCAction(string s )
    {
        Trace.WriteLine(s);
    }
...
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Does it still have the Jass Limitations, eg. adding parameters to the action calls?

JASS:
...
    private void Script_PostMain()
    {
        string s = "ESC"
        var trigger = JassTrigger.Create();
        trigger.RegisterPlayerEvent(JassPlayer.FromIndex(0), JassPlayerEvent.EndCinematic);
        trigger.AddAction(new Action(this.ESCAction(s)));
    }

    private void ESCAction(string s )
    {
        Trace.WriteLine(s);
    }
...
I could definitely implement that, a sort of "state" object, which is popular in .NET. Basically, it can be anything, a string, int, array of ints, or even a full class, and have it passed around. I'll make sure to implement that.

It's already possible to use anonymous methods with this.

JASS:
...
    private void Script_PostMain()
    {
        string s = "ESC"
        var trigger = JassTrigger.Create();
        trigger.RegisterPlayerEvent(JassPlayer.FromIndex(0), JassPlayerEvent.EndCinematic);
        trigger.AddAction(new Action(() => { Trace.WriteLine(s); }));
    }
...
 
Level 4
Joined
May 25, 2009
Messages
100
Cool ^^ will it be constant then? Like when you declare the action and your state object is "1" and you do some stuff and change it to "2" and now the trigger gets fired...is it "1" or "2" in the action?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Cool ^^ will it be constant then? Like when you declare the action and your state object is "1" and you do some stuff and change it to "2" and now the trigger gets fired...is it "1" or "2" in the action?

Basically like the vJASS attempt vexorian always wanted to implement. Unless it's an under the hood change like adding natives is, then it won't interpret the locals the way you want it to.

If, however, he puts the change under the hood, then you no longer need timer systems and most spells won't need a data managing system and the learning curve will drop.

So, long story short, I am curious which method he would implement.
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Cool ^^ will it be constant then? Like when you declare the action and your state object is "1" and you do some stuff and change it to "2" and now the trigger gets fired...is it "1" or "2" in the action?

The state object can be anything, literally. So if you want it to be a single constant used value, you just pass a constant value. If you want to create a periodic heal effect on a unit, you can pass the unit as the state object and cast the state object to a unit in the callback and then update the health that way.

Here's a psuedocode example.
C#:
...
    private void CastHealOn(JassUnit caster, JassUnit target, Single amount, Single duration)
    {
        var healState = new HealState();
        healState.Caster = caster;
        healState.Target = target;

        if (new Random().NextDouble() <= 0.10) // 10 % chance of double heal and 50 % longer duration.
        {
            healState.Amount = amount * 2;
            healState.Duration = duration * 1.50f;
        }
        else
        {
            healState.Amount = amount;
            healState.Duration = duration;
        }

        healState.Trigger = JassTrigger.Create();
        healState.Trigger.RegisterTimerEvent(0.50f, true);
        healState.Trigger.AddAction(new ManagedAction(HealTick), healState);
    }

    private void HealTick(Object state)
    {
        var healState = (state as HealState);

        // use healState.Caster to award some experience to the caster for each heal effect.
        // use healState.Target to modify the targets health by healState.Amount.

        healState.Duration -= 0.50f;
        if (healState.Duration <= 0.00f)
        {
            healState.Trigger.Enabled = false;
            healState.Trigger.Destroy();
        }
    }

    class HealState
    {
        public JassUnit Caster;

        public JassUnit Target;

        public Single Amount;

        public Single Duration;

        public JassTrigger Trigger;
    }
...
I don't know if that's good code or not, I don't know if you're supposed to destroy triggers like that, but it'll give you an idea what can be done using the state object.
 
Level 16
Joined
Aug 7, 2009
Messages
1,403
Maybe I'm overthinking things, but I think a base class with a protected constructor (could be abstract too if a constructor in the base class is not necessary) would be pretty good here. It would have the following methods:

  • /virtual/ Condition(void) (defaults to true)
  • /virtual/ Action(void) (defaults to "donothing")
  • AddEvent(Type eventType,params Object[] parameters) / AddXYZEvent(<parameters>)
  • Enable(bool enabled)
  • possibly others too - only the first two, virtual ones are important for what I'm trying to say

People could just extend from it, override the necessary methods, and attach whatever else they want to the trigger instance. No need for parameters, typecasting, or anything similar. We're using C#, a pure OO language, after all.
 
Level 15
Joined
Feb 15, 2006
Messages
851
The state object can be anything, literally. So if you want it to be a single constant used value, you just pass a constant value. If you want to create a periodic heal effect on a unit, you can pass the unit as the state object and cast the state object to a unit in the callback and then update the health that way.

Here's a psuedocode example.
C#:
...
    private void CastHealOn(JassUnit caster, JassUnit target, Single amount, Single duration)
    {
        var healState = new HealState();
        healState.Caster = caster;
        healState.Target = target;

        if (new Random().NextDouble() <= 0.10) // 10 % chance of double heal and 50 % longer duration.
        {
            healState.Amount = amount * 2;
            healState.Duration = duration * 1.50f;
        }
        else
        {
            healState.Amount = amount;
            healState.Duration = duration;
        }

        healState.Trigger = JassTrigger.Create();
        healState.Trigger.RegisterTimerEvent(0.50f, true);
        healState.Trigger.AddAction(new ManagedAction(HealTick), healState);
    }

    private void HealTick(Object state)
    {
        var healState = (state as HealState);

        // use healState.Caster to award some experience to the caster for each heal effect.
        // use healState.Target to modify the targets health by healState.Amount.

        healState.Duration -= 0.50f;
        if (healState.Duration <= 0.00f)
        {
            healState.Trigger.Enabled = false;
            healState.Trigger.Destroy();
        }
    }

    class HealState
    {
        public JassUnit Caster;

        public JassUnit Target;

        public Single Amount;

        public Single Duration;

        public JassTrigger Trigger;
    }
...
I don't know if that's good code or not, I don't know if you're supposed to destroy triggers like that, but it'll give you an idea what can be done using the state object.
WHAT IS THIS SORCERY!!!!! :ogre_rage:

Or better, is this sorcery working?
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Maybe I'm overthinking things, but I think a base class with a protected constructor (could be abstract too if a constructor in the base class is not necessary) would be pretty good here. It would have the following methods:

  • /virtual/ Condition(void) (defaults to true)
  • /virtual/ Action(void) (defaults to "donothing")
  • AddEvent(Type eventType,params Object[] parameters) / AddXYZEvent(<parameters>)
  • Enable(bool enabled)
  • possibly others too - only the first two, virtual ones are important for what I'm trying to say

People could just extend from it, override the necessary methods, and attach whatever else they want to the trigger instance. No need for parameters, typecasting, or anything similar. We're using C#, a pure OO language, after all.
I'll have to see how well abstract classes work with MarshalByRefObject, but that's an even better solution. Perhaps allow both, as one way easily allows anonymous methods but the other allows more structured flow for systems.

WHAT IS THIS SORCERY!!!!! :ogre_rage:

Or better, is this sorcery working?
This is almost working sorcery. Right now I have an issue with the game state when I'm detecting the events. For some reason anything JassString related seems to crash, which is a bit limiting. This means no DisplayTextToPlayer, but creating units is fine. I'm sure I can come up with a solution, but it's taking longer than expected.
 
Level 16
Joined
Aug 7, 2009
Messages
1,403
I'll have to see how well abstract classes work with MarshalByRefObject, but that's an even better solution. Perhaps allow both, as one way easily allows anonymous methods but the other allows more structured flow for systems.

I'm glad you like the idea :) Yea, both of those things could/should be possible - in fact, mine could be even done based on what you posted:

C#:
public abstract class AutoTrigger
{
    public JassTrigger Trigger { get; private set; };

    public virtual bool Condition() { return true; }
    public virtual void Action() { }
    
    private static bool ConditionHandler(Object obj)
    {
        return (obj as AutoTrigger).Condition();
    }

    private static void ActionHandler(Object obj)
    {
        (obj as AutoTrigger).Action();
    }

    protected AutoTrigger()
    {
        this.Trigger=JassTrigger.create();
        this.Trigger.AddCondition(new ManagedCondition(ConditionHandler),this);
        this.Trigger.AddAction(new ManagedAction(ActionHandler),this);
    }

    ~AutoTrigger()
    {
        this.Trigger.Destroy();
    }
}

...

public class SpellExample: AutoTrigger
{
    //store your stuff here

    public override bool Condition()
    {
        //return true if the caster spell's id matches the spell's id
    }

    public override void Action()
    {
        // Do some fancy stuff here, using the things attached to your instance
    }

    public SpellExample()
    {
        this.Trigger.RegisterSpellEffectEvent();
        this.Trigger.Enabled=true;
    }
}

This is more like a pseudo-code, I don't really know what kind of typenames I'd need to use, so I based my example on yours. But I'm fairly sure you get the point. I also realized yesterday that just because we can't directly instantiate abstract classes, it doesn't mean they can't have constructors, so it'll work just fine :'D
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
If I get some free time away from studies I will put my hands on this. This is so fking interesting. Shame for being away from hive for 2 years. Btw, you have nothing against "putting my hands" on this, yo?

And if I'm here, does such script work on battle net? Ive read thread and it seems that answer is: yes. However it still seems to be risky. Im curious what blizz employes would say if this gets popular.
 
And if I'm here, does such script work on battle net? Ive read thread and it seems that answer is: yes. However it still seems to be risky. Im curious what blizz employes would say if this gets popular.

AFAIK it works. It is all local responses and stuff though. So you run the risk of desync if the other person doesn't have SharpCraft and you do something desyncy (e.g. you have a function that checks if a key is down. If the other user doesn't have sharpcraft, then it won't do anything, but it may pass for the user who does have sharpcraft. The action would then be evaluated only for the SharpCraft user, and if it, for example, creates a handle, then things will likely desync). Eh, but that is theoretical. I haven't tested it.

You can't get past the lobby with custom natives. With custom natives, you have to run the map through sharpcraft externally (unless, maybe, you include a custom common.j or something?). You can, however, override natives. That way, you can offer special functionality to those who have SharpCraft, and the other people who don't have it can still load the game.

And I think Luorax summed up Blizz's potential response quite nicely. ;)
 
AFAIK it works. It is all local responses and stuff though. So you run the risk of desync if the other person doesn't have SharpCraft and you do something desyncy (e.g. you have a function that checks if a key is down. If the other user doesn't have sharpcraft, then it won't do anything, but it may pass for the user who does have sharpcraft. The action would then be evaluated only for the SharpCraft user, and if it, for example, creates a handle, then things will likely desync). Eh, but that is theoretical. I haven't tested it.

You can't get past the lobby with custom natives. With custom natives, you have to run the map through sharpcraft externally (unless, maybe, you include a custom common.j or something?). You can, however, override natives. That way, you can offer special functionality to those who have SharpCraft, and the other people who don't have it can still load the game.

And I think Luorax summed up Blizz's potential response quite nicely. ;)
Don't get me wrong; it allows to do *some* things, but let's face it: if one of the players doesn't have SharpCraft, then it's use will be so extremely limited that it doesn't justify using SharpCraft at all. ;)

I think you are just overcomplicating things by trying to allow a non-SharpCrafter play the map by replacing natives instead of adding custom natives. It has almost no practical use.
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
Don't get me wrong; it allows to do *some* things, but let's face it: if one of the players doesn't have SharpCraft, then it's use will be so extremely limited that it doesn't justify using SharpCraft at all. ;)

I think you are just overcomplicating things by trying to allow a non-SharpCrafter play the map by replacing natives instead of adding custom natives. It has almost no practical use.

Practical uses would include a chat system, online score system and even a tournament streaming service where people could spectate competitive games from a website. I could see a system that allows Twitch streamers to see the chat from viewers while in a game. There are plenty of uses for client-only modifications. That being said, personally, I think the most interesting is complete overhauls, but that's a bit more challenging to get people to use.
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
When the player limit is abolished AND you can join the game whenever you want there can be a "Twitch plays Warcraft 3" :D
:mwahaha::mwahaha::mwahaha:

+rep
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
New release!

Changelog
Code:
v2.2.5.124b
 * Expanded the managed JASS type wrappers.
 * Implemented script-side events (issue #4) 
 * Implemented new method for calling natives with strings, resulting in more speed, since we're avoiding conversion.
 * Implemented a better method for adding trigger actions.
 * Implemented a few more Jass types.
 * Minor improvement for the InternalNatives.JassStringHandleToString if check.
 * Added missing DelegateAction type.
 * Included commit number in the version number.
 * Fixed a bug with returned JassStrings when calling natives directly.
 
Last edited:
Level 1
Joined
Dec 15, 2012
Messages
6
Is there a real possibility to create own user interface, disable the default UI or at least reduce the default UI due to the resolution (16:10) ??? (through dll injecting or hacking). (Yes, i know is impossible (in this time) disable user interface with minimap, inventory, hero portrait etc.., because it need knowledge about warcraft III code and i read somewhere here on hive that game not render graphic "under" user interface. )
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
The game does indeed not render under it. If you switch to letterbox/cinematic view, you get an idea of the amount of screen that actually renders. It might be possible to increase the render area, but to do that, I need a much more intimate knowledge of how DirectX work, and that's knowledge I don't have.
 

MindWorX

Tool Moderator
Level 20
Joined
Aug 3, 2004
Messages
709
I've come to the conclusion that SharpCraft has started suffering from feature creep.
This means that next release will have a lot of the main features stripped away, in favor of a cleaner modding API. The existing advanced features will be moved into plugins.
Also, the sandbox is causing more issues than it's worth, so for now, that's going away as well. Hopefully this means SharpCraft will become a clean lean modding machine and not require as many updates as it currently needs.
I realize this changes the modding API drastically once more, but hopefully this will be the last major change for a while.
 
Status
Not open for further replies.
Top