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

Spells & Systems Mini-Contest #19

Status
Not open for further replies.

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Welcome to The Hiveworkshop's

btnchuck.jpg


Spells & Systems Mini-Contest #19

Introduction
The Spells & Systems Contest is more of a fun code learning environment than a contest, due to its low requirements, its short time limit, and its small prize. Each spell must adhere to the theme listed below, and to win, it should be executed well and take the main judging points into consideration.

Task
This contest's theme is

Comedy

The spell must do something funny yet creative enough to still be viable to use in a serious map. Can be light humor, dark humor, slapstick humor, but not obscene things.
Rules
1. All work should be done by the contestant and original to this contest, started after the contest started.
2. Each contestant is only allowed one submission.
3. The spell map must be unprotected.
4. Please post the triggers in
  • tags (JASS in [code=jass] tags)
    • 5. Imported material, beyond a dummy model, is strictly forbidden.
    • 6. Spells should support multiple levels, preferably an indefinite amount.
    • 7. The testmap should provide an adequate testing environment for the spell.
    • 8. GUI, JASS, vJass and Zinc are allowed.
    • 9. Third-party tools are supported, but the spell must be playable on Battle.net and editable in World Editor (GUI) or Jass NewGen Pack (vJass).
    • 10. vJass users, you may use other libraries to complement your code, some useful examples:
      • [list][*]TimerUtils[*]UnitIndexer[*]DamageEvent[*]Table[/LIST]
  • If you break the rules, you may be disqualified from the contest, but minor offences (Such as an imported model/icon) will generally be punished simply by the ignoring of them (as if it didn't exist) in the scoring, and a penalty in the related category.[/BOX]
  • [BOX=Entering] [COLOR="silver"]There is no specific required entry method. Just say you wish to enter, or post your spell when it's finished. Whatever works for you.[/COLOR][/BOX]
  • [BOX=Judging]
  • Judging will be as follows:
    • 1. [COLOR="silver"]Idea (5 points)[/COLOR] - Originality and execution of the idea.
    • 2. [COLOR="silver"]Triggering (5 points)[/COLOR] - Make efficient, leakless, simple triggers..
    • 3. [COLOR="silver"]Overall Aspect (5 points)[/COLOR] - Making sure your spell is easy to read (tooltip, comments, logical variable names), as well as having a practical use in-game.
    • 4. [COLOR="silver"]Visual effects (7 points)[/COLOR] - A nice-looking, non-laggy effect. Again, don't use custom models, achieve the effect with native WarCraft III models.
    • 5. [COLOR="silver"]Lulz (8 points)[/COLOR] - Slapstick humor, dry humor, please refrain from obscene humor.
  • [/BOX]
  • [BOX=Prize]
  • A spell can earn a maximum of 30 points. It's simple, the contestant with the most points wins.
  • [COLOR="silver"]The winner's prize will be 10 reputation points, and earn a spot in the "Spells/Systems Hall of Fame" (the list of winners of this contest).[/COLOR][/BOX]
  • [size=3]Contest is now closed :) Congratulations to our winners!
  • [COLOR="silver"]~Bribe[/COLOR][/SIZE]
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Even something like a funny little Moogle-type spell that just summons a little squirt that deals a huge, mighty attack would be considered "funny" ;)

I advise doing some brainstorming to come up with your spell. Write down all the first things that come to mind - remember - when brainstorming, bad ideas are welcome. Come up with a list of like 10 ideas. Some of them might be really bad ideas, but write them down anyway because that gets your creativity stirring. When you have a list of 10, odds are you've got 3-4 decent ideas and from there you can work.
 
Level 3
Joined
Aug 20, 2010
Messages
71
If I find out that I have some time, I will join.

Maybe a nice spell will be the mighty croud:
and I am between: one target ( you call the croud to smash 1 target and targets mixed in this fight ... might have a huge problem)

no target (the croud runs forward throw low healthed enemies in path, in the air and "I am not sure yet how" somehow dealing damage to other enemy units)
 
I might be in.

I'll create a spell that summons a little kid who runs around the
targeted unit spinning him 360 degrees 2-3 times each second
for 5 seconds. It would make the unit "dizzy" and reduce his
armor + add a slow effect.

OR

A knockback system that makes the targeted unit fart constantly
during the knockback and in intervals after it.

OR

A fart spell :p

OR

A spell that constantly impales the targeted unit and play the Warden
"shreek" sound per impale, but that would count as OBSCENE humor
LMAO (Me and my perverted mind)

OR

A spell in which the caster says a lame joke and suddenly all units in range are asleep :p

OR

.... I got nothing
 
Level 6
Joined
Oct 10, 2009
Messages
1,425
Make a unit slowly inflate and turn blue like a giant blueberry, until they eventually explode.
(willy wonka and the chocolate factory...for those who have seen it.)

Now whether or not I have time to actually do this idea is another story.
I will try though.
^_^
 
Level 3
Joined
Aug 20, 2010
Messages
71
maybe a nice spell will be the : summon the fart dragon (if stacks are more than 2 (max 6) then the hero farts and summons the fart dragon else he just farts)
 
Level 11
Joined
May 31, 2008
Messages
698
Heres my possible ideas:

Critter Cannonade - Launches various critters to a target area. The critters explode and deal aoe damage upon striking the ground.
(the critters spin through the air as they are launched)

Dragon thing - Summons a dragon that poops out lazer shooting flying sheep. After the dragon is finished, he eats all of the sheep and becomes bloated and explodes, dealing aoe damage to wherever he happens to be.
(have to think of a better name :p)
 
Level 10
Joined
Jul 12, 2009
Messages
318
I believe my entry will be "Loljuvination". Unused ideas: healing or "A.R.S.E." mines from TotalBiscuit and The Yoggscast Play Magicka, or a bright, flashy, visually overwrought spell that does something anticlimactic (eg. 3 damage).

I wonder whether the judging of the triggers also considers the choice of systems it uses, eg. would picking TimerUtils for short period timers be penalized?

I also wonder whether utilizing object editor abilities instead of triggering the related action would be considered better (simpler triggers) or worse (less dynamic)?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I can see what is triggered and what is not. As long as it remains a simple matter of copy+paste, the object editor ability can produce sounds, special effects and deal the damage.

TimerUtils for periods lower than 0.05 is a waste. A single timer looping through all instances is preferred, but depending on the quality of the rest of the script that will not cause any tremendous scoring problems.
 
Level 10
Joined
Jul 12, 2009
Messages
318
Loljuvination

evc0fl.jpg

JASS:
// Loljuvination -- v1.02. -- by Weep
//
// It's Rejuvination, plus some side-effects: the periodic spawning of flowers,
// fuzzy critters, a chance to hex the target, and a chance to summon a demonic Infernal.
// Gotta be careful when weilding those powerful life-based spells...
//
// Requires:
//    Systems:
//       TimerUtils by Vexorian
//       DummyCaster by Jesus4Lyf
//       Any one of the following: AutoIndex by grim001, AIDS by Jesus4Lyf, UnitIndexer by Nestharus
//    Object Editor abilities:
//       Rejuvination (LOL)
//       Inferno (LOL)
//       Hex (LOL)
//
// Much of the level data is handled in the Object Editor abilities; furthermore, they must all have
// the same amount of levels, if you wish to change that.

library Loljuvination initializer config requires TimerUtils, DummyCaster, optional AIDS, optional AutoIndex, optional UnitIndexer //I don't know how to make a library require any one of multiple compatible libraries...
	//===================================================================
	// Rawcodes and boring data.
	
	// Abilities
	globals
		//The base ability used by the hero, and its buff.
		private constant integer BASE_ABILITY = 'A000' //Rawcode of "Rejuvination (LOL)"
		private constant integer BASE_BUFF = 'Brej'
		
		//A point-targeted ability with a chance to be cast at the position of the target.
		private constant integer POINT_ABILITY = 'A001' //Rawcode of "Inferno (LOL)"
		private constant string POINT_ABILITY_ORDER = "dreadlordinferno"
		
		//A unit-targeted ability with a chance to be cast on the target.
		private constant integer TARGET_ABILITY = 'A002' //Rawcode of "Hex (LOL)"
		private constant string TARGET_ABILITY_ORDER = "hex"
	endglobals
	
	//Spell level information
	private function ProcForCritter takes integer level returns boolean //This is checked every PERIOD
		return GetRandomInt(1, 100) <= 30
	endfunction
	
	private function ProcForEffect takes integer level returns boolean //This is checked every PERIOD
		return GetRandomInt(1, 100) <= 60
	endfunction
	
	private function ProcForPointSpell takes integer level returns boolean //This is checked every PERIOD
		return GetRandomInt(1, 100) <= 2+level/2
	endfunction
	
	private function ProcForTargetSpell takes integer level returns boolean //This is checked every PERIOD
		return GetRandomInt(1, 100) <= 8-level
	endfunction
		
	// Constant Data
	globals
		//Period on which to run this spell's checks
		private constant real PERIOD = 0.5
		
		//Effects with duration made periodically on the ground
		private string array DOODAD_EFFECTS_TYPE
		private integer DOODAD_EFFECTS_TYPE_COUNT
		private constant real DOODAD_EFFECTS_MAX_OFFSET = 100. //So they will be made near the target
		private constant real DOODAD_EFFECT_EXPIRATION_TIME = 40. //Duration before removing effects
		
		//An effect played when a critter is spawned
		private constant string CRITTER_SUMMON_EFFECT = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
		private constant string CRITTER_SUMMON_EFFECT_ATTACHMENT = "origin"
		
		private constant real CRITTER_EXPIRATION_TIME = 120. //Duration of life of the spawned critters
		private constant integer CRITTER_EXPIRATION_BUFF = 'Btdg' //Timed life buff
		
		private integer array CRITTER_TYPES_GROUND
		private integer CRITTER_TYPE_GROUND_COUNT
		
		private integer array CRITTER_TYPES_FLYING
		private integer CRITTER_TYPE_FLYING_COUNT
	endglobals
	
	private function config takes nothing returns nothing
		//Preferably cute and fuzzy animals
		set CRITTER_TYPES_GROUND[0] = 'nech' //Chicken
		set CRITTER_TYPES_GROUND[1] = 'necr' //Rabbit
		set CRITTER_TYPES_GROUND[2] = 'nrac' //Raccoon
		set CRITTER_TYPES_GROUND[3] = 'nsea' //Seal
		set CRITTER_TYPES_GROUND[4] = 'nshe' //Sheep
		set CRITTER_TYPE_GROUND_COUNT = 4
		
		set CRITTER_TYPES_FLYING[0] = 'nalb' //Albatross
		set CRITTER_TYPES_FLYING[1] = 'nsno' //Snowy Owl
		set CRITTER_TYPES_FLYING[2] = 'nvul' //Vulture
		set CRITTER_TYPES_FLYING[3] = 'nshf' //Flying Sheep
		set CRITTER_TYPE_FLYING_COUNT = 3
		
		//Flowers!
		set DOODAD_EFFECTS_TYPE[0] = "Doodads\\Ruins\\Plants\\Ruins_Flower\\Ruins_Flower0.mdl"
		set DOODAD_EFFECTS_TYPE[1] = "Doodads\\Ruins\\Plants\\Ruins_Flower\\Ruins_Flower1.mdl"
		set DOODAD_EFFECTS_TYPE[2] = "Doodads\\Ruins\\Plants\\Ruins_Flower\\Ruins_Flower2.mdl"
		set DOODAD_EFFECTS_TYPE[3] = "Doodads\\Ruins\\Plants\\Ruins_Flower\\Ruins_Flower3.mdl"
		set DOODAD_EFFECTS_TYPE[4] = "Doodads\\Ruins\\Plants\\Ruins_Flower\\Ruins_Flower4.mdl"
		set DOODAD_EFFECTS_TYPE_COUNT = 4
		
		//Preloading
		call UnitAddAbility(DUMMY, POINT_ABILITY)
		call UnitRemoveAbility(DUMMY, POINT_ABILITY)
		call UnitAddAbility(DUMMY, TARGET_ABILITY)
		call UnitRemoveAbility(DUMMY, TARGET_ABILITY)
	endfunction
	
	//===================================================================
	// Spell code begins here.	Don't edit unless you're confident!
	//===================================================================
	private struct TimedEffect
		private effect theEffect
		
		private static method expire takes nothing returns nothing
			local thistype this = thistype(GetTimerData(GetExpiredTimer()))
			call ReleaseTimer(GetExpiredTimer())
			call DestroyEffect(.theEffect)
			call this.destroy()
		endmethod
		
		static method create takes effect e, real expiration returns thistype
			local thistype this = thistype.allocate()
			local timer t = NewTimer()
			set .theEffect = e
			call SetTimerData(t, this)
			call TimerStart(t, expiration, false, function thistype.expire)
			set t = null
			return this
		endmethod
	endstruct
	
	private struct Loljuvination extends array //WC3-style buffs are one-instance-per-target!
		private unit target
		private player casterOwner
		private integer level
		private boolean pointTargetProcced
		private timer period
		
		private static method periodicActions takes nothing returns nothing
			local thistype this = thistype[GetTimerData(GetExpiredTimer())]
			local real targetX = GetUnitX(.target)
			local real targetY = GetUnitY(.target)
			
			if GetUnitAbilityLevel(.target, BASE_BUFF) > 0 then
				if ProcForCritter(.level) then
					//Create a cute critter of the proper movement type for the target
					if IsUnitType(.target, UNIT_TYPE_FLYING) then
						//Why declare a new local or global when there's already one for this purpose?
						set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CRITTER_TYPES_FLYING[GetRandomInt(0, CRITTER_TYPE_FLYING_COUNT)], targetX, targetY, GetRandomReal(0, 360)) 
					else
						set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CRITTER_TYPES_GROUND[GetRandomInt(0, CRITTER_TYPE_GROUND_COUNT)], targetX, targetY, GetRandomReal(0, 360))
					endif
					call DestroyEffect(AddSpecialEffectTarget(CRITTER_SUMMON_EFFECT, bj_lastCreatedUnit, CRITTER_SUMMON_EFFECT_ATTACHMENT))
					call UnitApplyTimedLife(bj_lastCreatedUnit, CRITTER_EXPIRATION_BUFF, CRITTER_EXPIRATION_TIME)
				endif
				
				if ProcForEffect(.level) then
					//Make a timed effect
					call TimedEffect.create(AddSpecialEffect(DOODAD_EFFECTS_TYPE[GetRandomInt(0, DOODAD_EFFECTS_TYPE_COUNT)], targetX+GetRandomReal(-1, 1)*DOODAD_EFFECTS_MAX_OFFSET, targetY+GetRandomReal(-1, 1)*DOODAD_EFFECTS_MAX_OFFSET), DOODAD_EFFECT_EXPIRATION_TIME)
				endif
				
				if ProcForPointSpell(.level) and not .pointTargetProcced then
					//Cast the point-target ability using DummyCaster for the spell's caster's player
					call SetUnitOwner(DUMMY, .casterOwner, false)
					call UnitAddAbility(DUMMY, POINT_ABILITY)
					call SetUnitAbilityLevel(DUMMY, POINT_ABILITY, .level)
					call IssuePointOrder(DUMMY, POINT_ABILITY_ORDER, targetX, targetY)
					//Be a good citizen and reset the dummy
					call UnitRemoveAbility(DUMMY, POINT_ABILITY)
					call SetUnitOwner(DUMMY, Player(PLAYER_NEUTRAL_PASSIVE), false)
					set .pointTargetProcced = true //It would be a bit imba to cast more than once per buffing
				endif
				
				if ProcForTargetSpell(.level) then
					//Cast the unit-target ability using DummyCaster
					call SetUnitOwner(DUMMY, Player(PLAYER_NEUTRAL_PASSIVE), false) //In case somebody else was careless
					call UnitAddAbility(DUMMY, TARGET_ABILITY)
					call SetUnitAbilityLevel(DUMMY, TARGET_ABILITY, .level)
					call IssueTargetOrder(DUMMY, TARGET_ABILITY_ORDER, .target)
					//Be a good citizen and reset the dummy
					call UnitRemoveAbility(DUMMY, TARGET_ABILITY)
				endif
			else
				//IT'S OVER!
				call ReleaseTimer(.period)
				set .period = null
			endif
		endmethod
		
		private static method onCast takes nothing returns boolean
			local thistype this
			if GetSpellAbilityId() != BASE_ABILITY then
				return false
			endif
			
			set this = thistype[GetUnitId(GetSpellTargetUnit())] //One instance per target is the WC3 way.
			set .target = GetSpellTargetUnit()
			set .casterOwner = GetTriggerPlayer()
			set .level = GetUnitAbilityLevel(GetTriggerUnit(), BASE_ABILITY)
			set .pointTargetProcced = false
			
			if .period == null then //No need to restart things if they're already going from a previous cast
				set .period = NewTimer()
				call SetTimerData(.period, this)
				call TimerStart(.period, PERIOD, true, function thistype.periodicActions)
			endif
			
			return false
		endmethod
		
		private static method onInit takes nothing returns nothing
			local trigger t = CreateTrigger()
			call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
			call TriggerAddCondition(t, Condition(function thistype.onCast))
		endmethod
	endstruct
endlibrary

[EDIT] Attachment updated: tooltip typos.
[EDIT] Code and attachment updated: handle reference leak fixed, critter timed life added.
[EDIT] Code and attachment updated: privatized a method.
 

Attachments

  • Loljuvination.zip
    48.5 KB · Views: 89
Last edited:
Status
Not open for further replies.
Top