• 🏆 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!

HWC Artistic Mind - Team Alliance

  • Like
Reactions: deepstrasz
Spell submission for the HWC.
Code made by Chaosy
Models by Misha
Icons by Hayate

Artistic Mind:
Apheraz inspires all targets in an area, making their fantasies run rampant. Their own creations are unleashed on them. The creations last for 12/14/16 seconds unless killed. The creations will only deal damage to the origin.​

Shitty gif:
53485221ae42d3a25410d014e9f3dbb1.gif


JASS:
/*

    1. Copy the "Charm" and "Required" folder into your map unless you already have some
    of those libraries in your map, in which case you only need the missing ones.
 
    2. Import the required abilities/units from the object editor
 
 
    3. Make sure to edit the configs in the various libraries if you decide to use different IDs
    for your object editor units/spells.
*/

JASS:
native UnitAlive takes unit id returns boolean
//! zinc
    library ArtisticMind requires Missile, TimedUnitScale, TimerUtils, GroupTools, StunEngine {
 
        constant real GROW_TIME = 1;
        constant real CAST_TIME = 1;
        constant integer SPELL_ID = 'A003';
        constant string GROUND_FX = "Aphs Cast Effect.mdx";
        constant string MANIFEST_SPAWN_EFFECT = "Aphs Normal Effect.mdx";
        constant string MANIFEST_SPAWN_MISSILE = "Aphs Link Effect.mdx";
        constant real MANIFEST_COLOR = 80;
        constant real MANIFEST_SHRINK = 10;
        constant real MANIFEST_DURATION = 10;
        constant real MANIFEST_DURATION_INC = 2;
  
        integer lvl;
  
        hashtable hash = InitHashtable();
        group g;

        private function stun(unit u, real dur) {
            udg_STE_TARGET = u;
            udg_STE_DURATION = dur;
            udg_STE_STACK_TIME = true;
            udg_STE_ADD_STUN = true;
            TriggerEvaluate(udg_STE_TRIGGER);
        }
 
        private function getDuration(integer level) -> real {
            return 10 + (level * MANIFEST_DURATION_INC);
        }
 
        private struct Spawn {
            static method onFinish (Missile missile) -> boolean {
                timer t;
                integer h;
                integer level = LoadInteger(hash, missile, 0);
                unit target = LoadUnitHandle(hash, missile, 1);
                integer id = GetUnitTypeId(target);
                unit u = CreateUnit(Player(13), id, missile.x, missile.y, missile.angle);
          
                DestroyEffect(AddSpecialEffect(MANIFEST_SPAWN_EFFECT, GetUnitX(u), GetUnitY(u)));
                stun(u, GROW_TIME);
                SetUnitInvulnerable(u, true);
                SetUnitVertexColorBJ(u, MANIFEST_COLOR, MANIFEST_COLOR, MANIFEST_COLOR, 60);
                SetUnitScalePercent(u, MANIFEST_SHRINK, MANIFEST_SHRINK, MANIFEST_SHRINK);
                UnitScale[u].apply(1, GROW_TIME);
          
                t = NewTimer();
          
                h = GetHandleId(t);
          
                SaveBoolean(hash, GetHandleId(u), 1, true);
          
                SaveUnitHandle(hash, h, 0, u);
                SaveUnitHandle(hash, h, 1, target);
                SaveInteger(hash, h, 2, level);
          
                TimerStart(t, GROW_TIME, false, function() {
                    timer t = GetExpiredTimer();
                    integer id = GetHandleId(t);
                    unit u = LoadUnitHandle(hash, id, 0);
                    unit origin = LoadUnitHandle(hash, id, 1);
                    integer level = LoadInteger(hash, id, 2);
              
                    IssueTargetOrder(u, "attack", origin);
              
                    SetUnitInvulnerable(u, false);
                    UnitApplyTimedLife(u, 'BTLF', getDuration(level));
              
                    FlushChildHashtable(hash, id);
                    ReleaseTimer(t);
              
                    SaveUnitHandle(hash, GetHandleId(u), 0, origin);
              
                    t = null;
                    u = null;
                    origin = null;
                });
          
                FlushChildHashtable(hash, missile);
          
                u = null;
                target = null;
                t = null;
                return true;
            }
            module MissileStruct;
        }
  
        private function groupLoop() {
            unit u = GetEnumUnit();
            real x = GetUnitX(u);
            real y = GetUnitY(u);
      
            Missile m =  Missile.create(x, y, 75, GetRandomReal(0, 360), 400, 50);
      
            SaveInteger(hash, m, 0, lvl);
            SaveUnitHandle(hash, m, 1, u);
      
            m.speed     = 10.;
            m.model     = MANIFEST_SPAWN_MISSILE;
            m.arc       = bj_PI/4;
            Spawn.launch(m);
      
            u = null;
        }
  
        private function isManifestation(unit u) -> boolean{
            return LoadBoolean(hash, GetHandleId(u), 1);
        }
  
        private function onCastFilter(unit u, player p) -> boolean {
            return UnitAlive(u) && !isManifestation(u) && IsUnitEnemy(u, p);
        }
  
        private function onDelay() {
            timer t = GetExpiredTimer();
            integer h = GetHandleId(t);
            real x = LoadReal(hash, h, 1);
            real y = LoadReal(hash, h, 2);
            unit u = LoadUnitHandle(hash, h, 0);
      
            DestroyEffect(LoadEffectHandle(hash, h, 3));
      
            FlushChildHashtable(hash, h);
            ReleaseTimer(t);
            t = null;
      
            g = NewGroup();
            GroupUnitsInArea(g, x, y, 300);
      
            h = GetHandleId(g);
            SavePlayerHandle(hash, h, 0, GetOwningPlayer(u));
      
            ForGroup(g, function () {
                unit u = GetEnumUnit();
                player p = LoadPlayerHandle(hash, GetHandleId(g), 0);
                if(!onCastFilter(u, p)) {
                    GroupRemoveUnit(g, u);
                }
                p = null;
                u = null;
            });
      
            FlushChildHashtable(hash, h);
  
            lvl = GetUnitAbilityLevel(u, SPELL_ID);
  
            ForGroup(g, function groupLoop);
            ReleaseGroup(g);
        }
  
        private function onCast() {
            real x = GetSpellTargetX();
            real y = GetSpellTargetY();
            unit u = GetSpellAbilityUnit();
            timer t = NewTimer();
            integer h = GetHandleId(t);
            SaveEffectHandle(hash, h, 3, AddSpecialEffect(GROUND_FX, x, y));
      
            SaveUnitHandle(hash, h, 0, u);
            SaveReal(hash, h, 1, x);
            SaveReal(hash, h, 2, y);
      
            TimerStart(t, CAST_TIME, false, function onDelay);
      
            u = null;
            t = null;
        }
  
        private function filter() -> boolean{
            return GetSpellAbilityId() == SPELL_ID;
        }
  
        private function isSet(unit u) -> boolean {
            return u != null;
        }
  
        private function onDamage() {
            unit origin = LoadUnitHandle(hash, GetHandleId(udg_DamageEventSource), 0);
            if (origin != udg_DamageEventTarget && isSet(origin)) {
                udg_DamageEventAmount = 0.00;
            }
            origin = null;
        }
  
        private function onDeathFilter() -> boolean{
            return isManifestation(GetFilterUnit());
        }
  
        private function onDeath() {
            FlushChildHashtable(hash, GetHandleId(GetTriggerUnit()));
        }
  
        private function onInit() {
            trigger t = CreateTrigger();
            TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
            TriggerAddCondition(t, Condition(function filter));
            TriggerAddAction(t, function onCast);
      
            t = CreateTrigger();
            TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH);
            TriggerAddCondition(t, Condition(function onDeathFilter));
            TriggerAddAction(t, function onDeath);
      
            t = CreateTrigger();
            TriggerRegisterVariableEvent(t, "udg_DamageModifierEvent", EQUAL, 1.00);
            TriggerAddAction(t, function onDamage);
      
            t = null;
        }
    }
//! endzinc
Contents

HWC - Artistic Mind (Map)

Reviews
KILLCIDE
Simple concept, but the missile effects making it pretty interesting. Based off Cokemonkey's review, this spell is in an approvable state. Needs Fixed Nothing Suggestions Consider Cokemonkey's suggestions to improve the code / concept Status Approved
Top