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

Zephyr Contest #14 - Unique Summoning

Status
Not open for further replies.
Level 13
Joined
Jun 20, 2014
Messages
479
ill claim this concept - the caster creates a summoning circle and a creature will be summoned after a short delay.

Edit: just to clarify, summoned unit has to be killable? moving, fighting etc? i plan mine to be a unit with locust ability which will attack, buff or heal for a duration. Or it should be a real unit? Also, crypt lord's ulti is a summoning skill, is it not?
 
Last edited:
re:

Forgot to ask questions:
- Are sub-abilities allowed? if so, how many?
- Can summoned units receive abilities? if so, what is the max number of abilities? can a behavior function like an ability, even though the summoned unit don't have the "ability"(i'm pointing on to the object)?

nobody saw my edited post :V
 
Last edited:
Level 37
Joined
Jul 22, 2015
Messages
3,485
The contest has officially began?

Whenever the host thinks the 28th of April is. It's still the 27th for me.

contest%20dates%20and%20deadline.png
  • The contest shall begin on 28th of April and conclude on 29th of May (day is included).
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Not sure if I lose coding points for not adding a feature.
If it is judged as a system, maybe? This is supposed to be a spell so I don't think you would :p


On a side note, it is finally the 28th on my side of the planet! First WIP incoming:
Animation.gif

I still have no concept, I just know I want something falling from the sky. I'm also not sure if I will be able to finish the entry by the deadline considering I only have a couple hours a week to work on it ;_; the code so far is already starting to become convoluted (I have a love-hate relationship with GUI), so I might have to scratch this idea and go back to the drawing board. I hope to see more WIPs when I get back from school later!
 
Level 13
Joined
Jun 20, 2014
Messages
479
i just wanna mention, the theme of the contest unique summoning. we have to worry about the summoning mechanics itself and we also have to worry about what to summon. where does the judging will focus on exactly? the part where we summon or the part where the unit is actually summoned? is there already a discussion about this?
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
requires 7+ libraries to work (OH YEAH)
I hope you die a painful death.
not really

Anyway, this is what I've done so far:
First time using a linked list so I hope I am using it correctly lol.
JASS:
//! zinc
	library AlchemistCreation requires LinkedList
	{
		public List recipes;
		
		public function PrepareCraft(unit u)
		{
			integer i = 0;
			Link x = recipes.first;
			while(i < recipes.size)
			{
				ItemRecipe(x.data).Craft(u);
				x = x.next;
				i = i + 1;
			}	
		}
		
		function Actions()
		{
			unit u = GetManipulatingUnit();
			if(GetUnitTypeId(u) == 'H000')
			{
				AddSpecialEffect("Abilities\\Spells\\Orc\\AncestralSpirit\\AncestralSpiritCaster.mdl", GetUnitX(u), GetUnitY(u));
			}
		}
		
		function onInit()
		{
			trigger t = CreateTrigger();
			TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM);
			TriggerAddAction(t, function Actions);
			recipes = List.create();
		}
		
		public struct ItemRecipe
		{
			List parts;
			integer summon;			
			
			public method Craft(unit u)
			{
				integer i = 0;
				boolean check = true;
				Link l = parts.first;
				while(i < parts.size)
				{
					if(!UnitHasItemOfTypeBJ(u, l.data) == true)
					{
						check = false;
						break;
					}
					l = l.next;
					i += 1;
				}
				if(check)
				{
					CreateUnit(GetOwningPlayer(u), summon, GetUnitX(u), GetUnitY(u), 0);
					RemoveItem(GetItemOfTypeFromUnitBJ(u, parts.first.data));
					RemoveItem(GetItemOfTypeFromUnitBJ(u, parts.first.next.data));
					AddSpecialEffect("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", GetUnitX(u), GetUnitY(u));
				}
			}
			
			method add(integer part)
			{
				Link.create(parts, part);
			}
			
			static method create(integer result) -> thistype
			{
				thistype this = thistype.allocate();
				summon = result;
				parts = List.create();
				Link.create(recipes, this);
				return this;
			}
		}
	}
//! endzinc
 
In certain cases "unique behaviour" might make a concept better and more great, if it fits your unit. You must decide.

where does the judging will focus on exactly? the part where we summon or the part where the unit is actually summoned?
The focus lies on all summoning aspects, as this is the theme. How the summoning starts, the whole process, and of course also what is the result after.
For example, if all is done very good, but the summoned unit is just a tree-looking unit which can't do nothing but playing a weirdid sound around, the judges might see some lost potential.

Summoning units doesn't need to be controllable or killable.

Locust Swarm already proved that ;)
Where was is proven?

I actually see Locust swarm in a critical way. The surrounding thingies seem more like dummies to me.
 
Level 11
Joined
Dec 19, 2012
Messages
411
Forgot to ask questions:
- Are sub-abilities allowed? if so, how many?
- Can summoned units receive abilities? if so, what is the max number of abilities? can a behavior function like an ability, even though the summoned unit don't have the "ability"(i'm pointing on to the object)?

IcemanBo, you may need to answer these questions so that the people wouldn't leave any doubt. :)

I actually see Locust swarm in a critical way. The surrounding thingies seem more like dummies to me.
So, from your point of view, Locust swarm doesn't consider as summons? If so, then any units that is non-controllable, non-killable are not consider as summons in this contest?
 
Fortune smiles upon me - I have some unexpected time to work on my entry that I had not previously expected: May have a WIP up by the end of the day

On a side note; I see a very obvious use/need of the bonus library for summoned units (given having 10 separate units when each level is slightly stronger than the last for a 10-level summon ability it's pretty nonsensical to implement - I know 10 levels is an exaggeration but it demonstrates my concern) I don't remember there being a JASS implementation of it

my question: Where is it if it exists and if not, what would be an acceptable/no points lost method for implementing stat-differing summoned units when utilising JASS? given implementing multiple summon[level] = unit lines would be pretty ugly and far away (as it'd be in the initTrig function) from the constant function configuration for standard JASS abilities

The best I could come up with would be having contiguous unit IDs for the summoned units (A001, A002, A003, etc.) but then it becomes awkward to import since you'd need to make sure those IDs were contiguous in the imported map

Edit: for the record I don't consider locust swarm a summon - the locusts to all intents and purposes are special effects: They have 0 summon-like characteristics beyond appearance; if I change cluster rocket's projectiles to be sheep, is it now a summon ability? to clarify at least to me the following characteristics are "summon like":
- More than a single behaviour (locusts can only drain health, they do not otherwise attack or move any other way)
- Are independent of their summoner (to some degree - locusts cannot move away from the caster and are bound to be next to them)
- Can be killed independently of their summoner (they have their own distinct HP/Armour, but this doesn't mean killing the summoner can't kill them)
- Can use their own abilities (Pocket factory robots explode, feral spirits are invisible and can critical strike, fire elementals duplicate, carrion beetles can burrow)
- Register as independent damage sources from their summoner
There may be more but these are some of the more key things I think summons need (not to say they need all of them - water elementals have no unique abilities for example) but at least a few to really be a summon more than an effect that just looks like a unit

I'll also state that this is of course just my opinion - the judges will be the ones to decide what qualifies (perhaps a formal post on summon requirements would be a good idea)
 
Last edited:
- Are sub-abilities allowed? if so, how many?
It's defined: "Create a spell", which means one spell.
Given that information you can do everything you want of course and try to argue.
Though, the judgement might share or might not share your thoughts of concept.

Can summoned units receive abilities? if so, what is the max number of abilities? can a behavior function like an ability, even though the summoned unit don't have the "ability"(i'm pointing on to the object)?
The summoned unit behaviour is undefined. Of course, the unit having abilities is allowed.
I don't understand the "does it need pointing on the object" question. I don't know if the unit needs it, or not. You say.

We won't explicitly tell you guys how we expect the spell to be and to look like. This is a contest. Be creative.

So, from your point of view, Locust swarm doesn't consider as summons? If so, then any units that is non-controllable, non-killable are not consider as summons in this contest?
In my post where I linked to, I gave my best to explain what a dummy is, and what a unit is.
In locust swarm, the the particles are just there, you can't do nothing with it. They are just dummies that like only fly around the caster and indicate damage to nearby units.
Summon something that actually can do something.

Tank-Commander,
so your question is, if BonusMod is an allowed library? Judges will post on that.
 
Last edited:
so your question is, if BonusMod is an allowed library? Judges will post on that.

Well yes and no - since BonusMod is vJASS, implementing it in an otherwise JASS submission is all but pointless given that the primary reason to use JASS (at least from my perspective) is to keep it vanilla compatible and easy to import; having BonusMod as a requirement kind of defeats that point, hence the latter part of my question
 
Level 26
Joined
Oct 2, 2011
Messages
2,482
First Look WIP:
WIP%20Spell%20Contest.jpg

A demonic incarnation, restrained to its dark domain.
-It will attack anyone, even allies. (perhaps)
-Channeled ability. If caster is interupted, the summoning will end.
-Uncontrollable, but it will have a reactivatable ability, controlled by the caster.
-Selects and attacks units within its domain at random, stunning them briefly, and then slowing them.
-Attacks also steal the attacked units soul, creating a weak shadow to do the demons bidding.
 
@Tank-Commander: For vanilla JASS, I would recommend DoomLord's system:
http://www.hiveworkshop.com/forums/spells-569/jass-custom-stat-system-css-v1-5g-229885/

Otherwise, BonusMod.

If you find neither to be sufficient, then you can feel free to implement a portion of the system for whatever your spell needs (e.g. if you just need to have bonus damage, you can just make a bonus damage system). You won't lose points as long as it is implemented in a way that isn't wasteful.
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
By the way, I was thinking of adding some more 'features' to include for the item summoning of mine.

I wanted to add a % fail rate.

Basically I did:
set luck = random(1-100)
if luck < this.failRate then
//fail
endif

However I thought that this would be slightly faster, but I have no idea.

set luck = random(1-100)
if this.failRate > 0 and luck < this.failRate then
//fail
endif
 
Level 13
Joined
Jun 20, 2014
Messages
479
WIP Post

Concept
The caster creates a summoning circle. After a short delay a creature is conjured through the circle which last for a duration.

Spell Name: Call of the Damned
Description: Creates a summoning circle in which allows the caster to conjure powerful demons from another realm.


  • Call of the Damned Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set CD_Ability = Call of the Damned
      • Set CD_AoE[1] = 300.00
      • Set CD_AoE[2] = 300.00
      • Set CD_AoE[3] = 300.00
      • Set CD_CastingTime[1] = 30.00
      • Set CD_CastingTime[2] = 30.00
      • Set CD_CastingTime[3] = 30.00
      • Set CD_SummonedUnit[1] = Doom Guard
      • Set CD_SummonedUnit[2] = Doom Guard
      • Set CD_SummonedUnit[3] = Doom Guard
      • Set CD_CircleSfx1 = Abilities\Spells\Undead\VampiricAura\VampiricAura.mdl
      • Set CD_CircleSfx2 = Abilities\Spells\Undead\Unsummon\UnsummonTarget.mdl
      • Set CD_CircleUnitType = Dummy
  • Call of the Damned Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to CD_Ability
    • Actions
      • Set CD_Index = (CD_Index + 1)
      • Set CD_Caster[CD_Index] = (Triggering unit)
      • Set CD_Player[CD_Index] = (Triggering player)
      • Set CD_Level[CD_Index] = (Level of CD_Ability for CD_Caster[CD_Index])
      • Set CD_Angle[CD_Index] = (Facing of CD_Caster[CD_Index])
      • Set CD_Point1 = (Position of CD_Caster[CD_Index])
      • Set CD_Point2 = (CD_Point1 offset by CD_AoE[CD_Level[CD_Index]] towards CD_Angle[CD_Index] degrees)
      • Unit - Create 1 CD_CircleUnitType for CD_Player[CD_Index] at CD_Point2 facing CD_Angle[CD_Index] degrees
      • Set CD_CircleDummy[CD_Index] = (Last created unit)
      • Special Effect - Create a special effect attached to the origin of CD_CircleDummy[CD_Index] using CD_CircleSfx1
      • Set CD_Circle1[CD_Index] = (Last created special effect)
      • Special Effect - Create a special effect at CD_Point2 using CD_CircleSfx2
      • Set CD_Circle2[CD_Index] = (Last created special effect)
      • Animation - Change CD_CircleDummy[CD_Index]'s size to (CD_AoE[CD_Level[CD_Index]]%, 100.00%, 100.00%) of its original size
      • Set CD_Complete[CD_Index] = False
      • Set CD_TimeLeft[CD_Index] = CD_CastingTime[CD_Level[CD_Index]]
      • Custom script: call RemoveLocation(udg_CD_Point1)
      • Custom script: call RemoveLocation(udg_CD_Point2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CD_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on Call of the Damned Effect <gen>
        • Else - Actions
  • Call of the Damned Effect
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer CD_Looper) from 1 to CD_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of CD_Caster[CD_Looper]) Equal to (Order(starfall))
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_TimeLeft[CD_Looper] Greater than 0.00
                • Then - Actions
                  • Set CD_TimeLeft[CD_Looper] = (CD_TimeLeft[CD_Looper] - 0.03)
                • Else - Actions
                  • Set CD_Complete[CD_Looper] = True
                  • Unit - Order CD_Caster[CD_Looper] to Stop
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_Complete[CD_Looper] Equal to True
                • Then - Actions
                  • Set CD_Point1 = (Position of CD_CircleDummy[CD_Looper])
                  • Unit - Create 1 CD_SummonedUnit[CD_Level[CD_Looper]] for CD_Player[CD_Looper] at CD_Point1 facing CD_Angle[CD_Looper] degrees
                  • Unit - Add a 60.00 second Generic expiration timer to (Last created unit)
                  • Unit - Add classification of Summoned to (Last created unit)
                  • Custom script: call RemoveLocation(udg_CD_Point1)
                • Else - Actions
              • Special Effect - Destroy CD_Circle1[CD_Looper]
              • Special Effect - Destroy CD_Circle2[CD_Looper]
              • Unit - Add a 0.01 second Generic expiration timer to CD_CircleDummy[CD_Looper]
              • Set CD_Angle[CD_Looper] = CD_Angle[CD_Index]
              • Set CD_Caster[CD_Looper] = CD_Caster[CD_Index]
              • Set CD_Circle1[CD_Looper] = CD_Circle1[CD_Looper]
              • Set CD_Circle2[CD_Looper] = CD_Circle2[CD_Index]
              • Set CD_CircleDummy[CD_Looper] = CD_CircleDummy[CD_Index]
              • Set CD_Complete[CD_Looper] = CD_Complete[CD_Index]
              • Set CD_Level[CD_Looper] = CD_Level[CD_Index]
              • Set CD_Player[CD_Looper] = CD_Player[CD_Index]
              • Set CD_TimeLeft[CD_Looper] = CD_TimeLeft[CD_Index]
              • Set CD_Looper = (CD_Looper - 1)
              • Set CD_Index = (CD_Index - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CD_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions



Call of the Damned.png


Note: This is just a WIP and is far from how i see it done.
 

Attachments

  • Empirean Call of the Damned.w3x
    26 KB · Views: 90
Basically the chance of failing two times in a row (or more) is decreased?

edit: or that the fail rate increase after each success.

The chance increases whenever it fails to proc.

e.g. initial chance is 8 -> rolls -> fails -> increase chance by 8 -> current chance is 16 -> repeat step 2


but if you want some luck-based, you can disregard the idea of PRD
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
Some more progress.

I guess I should take it easy for a while now, the majority is already done.
JASS:
//! zinc
	library AlchemistCreation requires LinkedList, optional FloatingTextArc
	{
		public List recipes;
		constant string itemEffect = "Abilities\\Spells\\Other\\Transmute\\GoldBottleMissile.mdl";
		constant string green = "|c0096FF96";
		constant string yellow = "|c00FFFF00";
		constant string red = "|c00FF0000";
		constant string blue = "|c007EBFF1";
			
		constant string end = "|r";
		
		public constant integer cauldron = 'H000';
		
		public function PrepareCraft(unit u)
		{
			integer i = 0;
			boolean check;
			Link x = recipes.first;
			while(i < recipes.size)
			{
				check = ItemRecipe(x.data).Craft(u);
				x = x.next;
				i = i + 1;
			}
			static if(LIBRARY_FloatingTextArc)
			{
				if(!check)
				{
					ArcingTextTag.create(yellow + "That combination of items is invalid." + end, u);
				}
			}
		}
		
		function Actions()
		{
			unit u = GetManipulatingUnit();
			if(GetUnitTypeId(u) == cauldron)
			{
				DestroyEffect(AddSpecialEffect(itemEffect, GetUnitX(u), GetUnitY(u)));
				static if(LIBRARY_FloatingTextArc)
				{
					ArcingTextTag.create(blue + "Added: " + yellow + GetItemName(GetManipulatedItem()) + end + end, u);
				}
			}
			u = null;
		}
		
		function onInit()
		{
			trigger t = CreateTrigger();
			TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM);
			TriggerAddAction(t, function Actions);
			recipes = List.create();
		}
		
		public struct ItemRecipe
		{
			List parts;
			integer summon;			
			real failRate = 25;
			real dublicateChance = 25;
			real psuedoIncrease = 0;
			real timedLife = 0; // 0 = permanent (no timer)
			real numberOfFails = 0;
			real numberOfDublicates = 0; //used to calculate success/fail rate depending on streak
			
			string spawnEffect = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl";
			string failEffect = "Units\\NightElf\\Wisp\\WispExplode.mdl";
			
			public method Craft(unit u) -> boolean
			{
				integer i = 0;
				boolean check = true;
				real luck, x, y;
				unit temp;
				Link l = parts.first;
				while(i < parts.size)
				{
					if(!UnitHasItemOfTypeBJ(u, l.data))
					{
						check = false;
						break;
					}
					l = l.next;
					i += 1;
				}
				if(check)
				{
					luck = GetRandomReal(1,100);
					x = GetUnitX(u);
					y = GetUnitY(u);
					if(luck > failRate)
					{
						CreateUnit(GetOwningPlayer(u), summon, x, y, 0);
						if(timedLife > 0)
						{
							UnitApplyTimedLife(temp, 'BTLF', timedLife);
						}
						luck = GetRandomReal(1,100);
						DestroyEffect(AddSpecialEffect(spawnEffect, x, y));
						if(dublicateChance > 0 && dublicateChance > luck)
						{
							temp = CreateUnit(GetOwningPlayer(u), summon, x, y, 0);
							if(timedLife > 0)
							{
								UnitApplyTimedLife(temp, 'BTLF', timedLife);
							}
							static if(LIBRARY_FloatingTextArc)
							{
								ArcingTextTag.create(green + "Perfect brew! you created 2x: " + yellow + GetUnitName(temp) + end + end, u);
							}
						}
						else
						{
							static if(LIBRARY_FloatingTextArc)
							{
								ArcingTextTag.create(blue + "Success! You created: " + yellow + GetUnitName(temp) + end + end, u);
							}
						}
					}
					else
					{
						DestroyEffect(AddSpecialEffect(failEffect, x, y));
						static if(LIBRARY_FloatingTextArc)
						{
							ArcingTextTag.create(red + "Failed!" + end, u);
						}
					}
					RemoveItem(GetItemOfTypeFromUnitBJ(u, parts.first.data));
					RemoveItem(GetItemOfTypeFromUnitBJ(u, parts.first.next.data));
				}
				return check;
			}
			
			method add(integer part)
			{
				Link.create(parts, part);
			}
			
			static method create(integer result) -> thistype
			{
				thistype this = thistype.allocate();
				summon = result;
				parts = List.create();
				Link.create(recipes, this);
				return this;
			}
		}
	}
//! endzinc
  • demo init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: local ItemRecipe footman
      • Set unit = Footman
      • Custom script: set footman = ItemRecipe.create(udg_unit)
      • Set item = Kelen's Dagger of Escape
      • Custom script: call footman.add(udg_item)
      • Set item = Crown of the Deathlord
      • Custom script: call footman.add(udg_item)
  • demo test
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Alchemy Creation
    • Actions
      • Set test = (Target unit of ability being cast)
      • Custom script: if GetUnitTypeId(udg_test) == cauldron then
      • Custom script: call PrepareCraft(udg_test)
      • Custom script: else
      • Custom script: call ArcingTextTag.create("Invalid target, target a cauldron." , udg_test)
      • Custom script: endif
 
Level 11
Joined
Dec 19, 2012
Messages
411
You guys, are so fast..... I don't even able to finish my first part of my spell. Anywhere, here's my WIP code (not yet picture) :

JASS:
scope ElementalChaos initializer Init

//================================================================================
//============================Configurable Part===================================
//================================================================================
	globals
		//The spell id of the spell
		private	constant integer				SPELL_ID 				= 'A000'
		
		//Timer updating time constant
		private constant real		 			PERIODIC_TIME			= 0.03125
		
		//Summons Life Time (Configurable at function Init)
		private 		 real		 array		SUMMON_LIFE_TIME
	endglobals
	
	private function Init takes nothing returns nothing
		//[1] indicates Lv1, [2] indicates Lv2 and [3] indicates Lv3
		//Arrays are used instead of globals for preventing overwhelming globals as well as unnessasary coding.
		
		//Setting Summons Life Time
		set SUMMON_LIFE_TIME[1] = 10.
		set SUMMON_LIFE_TIME[2] = 10.
		set SUMMON_LIFE_TIME[3] = 10.
	endfunction
	
	private function getSphereGenerateTime takes integer spellLv returns real
		return 0.
	endfunction
	
	private function getSphereMaxScale takes integer spellLv returns real
		return 0.
	endfunction
//================================================================================
//==========================End Configurable Part=================================
//================================================================================





//================================================================================
//===========================Non-Configurable Part================================
//================================================================================
	globals
	endglobals
	
	private function getSpellDuration takes integer spellLv returns real
		return 0.
	endfunction
//================================================================================
//=========================End Non-Configurable Part==============================
//================================================================================


	//-----------------------------------------------------------------
	//-----------------------------------------------------------------
	//A linked list created by myself
	private module LinkedList
		//spell's instance count
		private static thistype instanceCount = 0
		
		//last allocated instance
		private static thistype lastNode
		
		private thistype next
		private thistype prev
		
		static method create takes nothing returns thistype
			local thistype this = instanceCount + 1
			set instanceCount = this
			
			if thistype(0).next == 0 then
				set thistype(0).next = this
				set lastNode = this
			else
				set lastNode.next = this
				set this.prev = lastNode
				
				set lastNode = this
			endif
			
			set this.next = 0
			set thistype(0).prev = this
			
			return this
		endmethod
		
		method destroy takes nothing returns nothing
			set this.prev.next = this.next
			set this.next.prev = this.prev
			
			if this.next == 0 and this.prev == 0 then
				set instanceCount = 0
			elseif lastNode == this then
				set lastNode = this.prev
			endif
			
		endmethod
	endmodule
	//-----------------------------------------------------------------
	//-----------------------------------------------------------------
	
	
	
	private struct ElementalSummon extends array
		implement LinkedList
	endstruct
	
	
	
	
	
	private struct ElementalChaos extends array
		implement LinkedList
		
		//============Elemental Chaos Globals=============
		private		static	timer		timerEC					= CreateTimer() //Elemental Chaos Timer
		
		private				unit		triggerUnit
		
		private				integer		spellLv
		
		private				real		spellDuration
		private				real		sphereGenerateTime
		private				real		sphereMaxScale
		private				real		sphereGenerateTimeConst
		//================================================
		
		
		private static method onPeriodic takes nothing returns nothing
		endmethod
		
		private static method onCast takes nothing returns boolean
			local thistype this
			
			if GetSpellAbilityId() == SPELL_ID then
				set this = thistype.create() //create a new instance
				
				//Storing data
				set this.triggerUnit				= GetTriggerUnit()
				set this.spellLv					= GetUnitAbilityLevel(this.triggerUnit, SPELL_ID)
				set this.spellDuration				= getSpellDuration(this.spellLv)
				set this.sphereGenerateTime			= getSphereGenerateTime(this.spellLv)
				set this.sphereMaxScale				= getSphereMaxScale(this.spellLv)
				set this.sphereGenerateTimeConst	= this.sphereGenerateTime/PERIODIC_TIME //a constant used for periodically increase the sphere (unit scale) to maximum scale.
				
				if this == 1 then
					call TimerStart(timerEC, PERIODIC_TIME, true, function thistype.onPeriodic)
				endif
			endif
			return false
		endmethod
		
		private static method onInit takes nothing returns nothing
			local trigger t = CreateTrigger()
			call TriggerAddCondition(t, Condition(function thistype.onCast))
			call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
			
			set t = null
		endmethod
	endstruct

endscope
 
Everybody is posting code WIPs so I'm gonna post mine as well:

JASS:
library ContractOfSuffering
    globals
        private constant integer ABIL_ID = 0
        /***********************************
        *
        *   Damage Proc
        *
        ***********************************/
        private constant real BASE_MAX_DAMAGE = 600
        private constant real MAX_DAMAGE_PER_LEVEL = -100
        private constant real DAMAGE_PROC_TIME = 10
        private constant real DAMAGE_PROC_TIME_PER_LEVEL = 0
        /***********************************
        *
        *   Embodiment Data
        *
        ***********************************/
        private constant real EMB_SPEED = 600
        private constant real EMB_SPEED_PER_LEVEL = 0
        
        private constant real EMB_ESCORT_RANGE = 800
        
        private constant boolean KILL_ON_ATK_COUNT = true
        private constant integer MAX_ATTACKS = 7
        private constant integer MAX_ATTACKS_PER_LEVEL = 3
        
        private constant real MAX_HP = 0
        private constant real MAX_HP_PER_LEVEL = 0
        
        private constant real LIFE_DURATION = 30
        private constant real LIFE_DURATION_PER_LEVEL = 10
        /***********************************
        *
        *   Level 1 : Shadow Assault
        *
        ***********************************/
        private constant integer EMB_STRIKE_LVL_REQ = 1
        private constant real EMB_ACQ_RANGE = 800
        
        private constant boolean EMB_IS_RANGED = false
        private constant real EMB_ATK_RANGE = 0
        
        private constant real EMB_MISSILE_SPEED = 0
        private constant real EMB_MISSILE_ARC = 0
        private constant string EMB_MISSILE_MODEL = ""
        
        private constant real EMB_ATK_COOLDOWN = 3.0
        private constant real EMB_ATK_COOLDOWN_PER_LEVEL = -5
        
        private constant boolean EMB_START_CD_IF_OUTRANGED = false
        private constant boolean EMB_START_CD_ON_RETURN = true
        
        private constant real EMB_ATK_DAMAGE = 0
        private constant real EMB_ATK_DAMAGE_PER_LEVEL = 50
        
        private constant boolean DAMAGE_THROUGH_UNITS = true
        private constant real EMB_PASS_DAMAGE = 0
        private constant real EMB_PASS_DAMAGE_PER_LEVEL = 15
        
        private constant string EMB_ACQUIRE_TARGET_SFX = ""
        private constant string EMB_ATK_RELEASE_SFX = ""
        private constant string EMB_ATK_DAMAGE_SFX = ""
        private constant string EMB_PASS_DAMAGE_SFX = ""
        /***********************************
        *
        *   Level 2 : Veil of Ordeal
        *
        ***********************************/
        private constant integer VEIL_LEVEL_REQ = 2
        
        private constant real MAX_DAMAGE_FEED = 100
        private constant real MAX_DAMAGE_FEED_PER_LEVEL = 25
        private constant real MAX_DAMAGE_TIME = 2
        private constant real MAX_DAMAGE_TIME_PER_LEVEL = 1
        private constant real DURATION_INC = 1
        private constant real DURATION_INC_PER_LEVEL = 1
        
        private constant real DAMAGE_HEAL_RATIO = 0.4
        private constant real DAMAGE_HEAL_RATIO_PER_LEVEL = 0.1
        
        private constant string VEIL_SFX = ""
        private constant string VEIL_ON_FEED_SFX = ""
        private constant string VEIL_ON_HEAL_SFX = ""
        /***********************************
        *
        *   Level 3 : Roar of Pain
        *
        ***********************************/
        private constant integer ROAR_LEVEL_REQ = 3
        
        private constant integer ROAR_REQUIRED_TARGETS = 3
        private constant real ROAR_DETECT_RANGE = 256
        private constant real ROAR_DETECT_OFFSET = 256
        
        private constant boolean ROAR_IS_CHARGED = true 
        private constant integer ROAR_MAX_CHARGES = 3
        private constant integer ROAR_MAX_CHARGES_PER_LEVEL = 1
        private constant real ROAR_CHARGE_REFRESH_RATE = 0
        private constant real ROAR_CHARGE_REFRESH_RATE_PER_LEVEL = 0
        
        private constant real ROAR_COOLDOWN = 10
        private constant real ROAR_COOLDOWN_PER_LEVEL = -1
        
        private constant real ROAR_CAST_TIME = 0.0
        private constant real ROAR_CAST_TIME_PER_LEVEL = 0
        
        private constant real ROAR_DISTANCE = 250
        private constant real ROAR_DISTANCE_PER_LEVEL = 250
        
        private constant real ROAR_SPEED = 500
        private constant real ROAR_SPEED_PER_LEVEL = 0
        
        private constant real ROAR_RADIUS = 256
        private constant real ROAR_RADIUS_PER_LEVEL = 0
        
        private constant real ROAR_DAMAGE = 0
        private constant real ROAR_DAMAGE_PER_LEVEL = 100
    endglobals
endlibrary

I made pretty much everything in the spell to be configurable.(The constants you see is not 100% complete, that's barely a part of it)
 
Concept:

Cast spell on enemy units. The target will receive a buff and a throw-away ability.
With the throw-away ability it has the chance, also to target enemies and throw the buff away, towards it's own enemies.
If the buff lasts at least for more than 3 seconds at the same unit, the ability will take effect.

onEffect the target will be slightly damaged and frozen, and some random neutral-hostile units will be spawned around it, depending on how often the buff was thrown away.
Also all other allied units that were affected by the buff before will be teleported to the target unit, ready to fight.

Along the neutral-hostile units, it might happen a boss-unit will be summoned which has a high chance to drop a good item and bring some good gold.
So the other player should not stay too far away from the fight, to have a fair chance also to kill the boss-unit, and pick up the item.

The item, dropped by the summoned boss, can be used to summon a hand of random elemental units, depending on the type of item.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
First Look WIP:

A demonic incarnation, restrained to its dark domain.
-It will attack anyone, even allies. (perhaps)
-Channeled ability. If caster is interupted, the summoning will end.
-Uncontrollable, but it will have a reactivatable ability, controlled by the caster.
-Selects and attacks units within its domain at random, stunning them briefly, and then slowing them.
-Attacks also steal the attacked units soul, creating a weak shadow to do the demons bidding.

Is that one big SFX model, or did you code those effects?
 
Level 19
Joined
Jul 2, 2011
Messages
2,162
I created the ability in my current working project map

how do I now prove I didn't create this months before hand?

I've got a few pictures but is there anything specifically I can uses as proof??? t
 
Status
Not open for further replies.
Top