- Joined
- Jun 24, 2009
- Messages
- 1,409
Then why won't you just remain at indexing?....
Ooooor why don't you just combinate hashtables and indexing?
Ooooor why don't you just combinate hashtables and indexing?
Then why won't you just remain at indexing?....
Ooooor why don't you just combinate hashtables and indexing?
. . . WHY WON'T THIS WORK, WHY!! It's all your fault baassee, you made me use hashtables again.
Berb, you could potentially check if a unit is still casting the ability...
(Current order of Caster_Gun) Equal to (Order(GunORDERID))
True, then do actions
False, then stop...
________________
Final Based on:
Thanks to Pharaoh_ , Maker and baassee |
Using no custom models will make that beam rather tricky, but if someone can pull it off well done in advance!
maybe we are allowed to modify the lightning data slk by hex editing the w3x file![]()
the "no imports" rule reduces the quality of the spell and I therefore think it's stupid
and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is ridiculous
all spell-ideas but mine are stupid so how can I make good spells by stealing others!
I won't take part (only contest I waited for![]()
I'm making a spell from a game i didn't even play D:and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is stupid
reminds me of the spell section with <random dota spell>, <random dota spell>, <random dota spell>, ...
D4RK_G4ND4LF said:and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is stupid
reminds me of the spell section with <random dota spell>, <random dota spell>, <random dota spell>, ...
D4RK_G4ND4LF said:and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is ridiculous
all spell-ideas but mine are stupid so how can I make good spells by stealing others!
Now you're changing your story! So which is it!
This is a Triggers & Scripts contest, not a Resources contest. I don't know where you find the lack of rationality there.
That's where the creativity comes into play.
I don't get it. You waited for this contest but since it has a theme and you're not allowed to artificially spice it with imports you're not going to take part in it. That's not a very good attitude!
if it improves the quality of the spell why forbid it?
creativity?
Google said:The use of the imagination or original ideas, esp. in the production of an artistic work
Google #2 said:Creativity is a mental process involving the discovery of new ideas or concepts, or new associations of the existing ideas or concepts, fueled by the process of either conscious or unconscious insight.
it's not that it HAS a theme but that it has THIS theme
If steroids improves the quality of athletes then why forbid it. It unbalances the playing field.
Not everybody is going to use nice imported models so those who do are going to have an obvious advantage. In addition custom models play a different role in every spell, so the advantages between people using imported models is going to vary.
Why add all these margins of error when you don't need to...
It's still not a good attitude.
imports are not allowed because making the spell look good using the default models is a part of spell making... and for me it actually shows the maker's creativity more... because making something look good without using AWESOME models is far more creative than making it look good just because you used something that is already good looking...
because there is a difference between inducing your talents and putting a barrier...and because the impact of no imports is considerably less than the impact of forcing everyone to use GUI...
and allowing imports will increase the map file size...
and yeah, if you don't like the rules, then don't join... no one forces you to join...
![]() | Shadow Armor | Shadow Armor summons a spirit to protect your character by attacking nearby foes, and increasing your block chance. The chance to evade an attack and armor duration increases with the level of attack |
//=======================Meteor Shower========================
//============================================================
//====================Made by: Mckill2009=====================
//============================================================
//=======Entry for: Spells & Systems Mini-Contest #20=========
//===HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- The trigger name MUST be >>> MeteorShower (see the name below)
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- If your raw code is different, you MUST CHANGE IT...
//- You can view the raw codes by pressing CTRL+B in the object editor
//- Examples of raw codes are 'A000', 'h000' etc...
//===REQUIRED VARIABLES:
//-HASH = Hashtable
//-Caster = Unit
//-Damage = Real
//===CONFIGURABLES:
//=====IMPORTANT NOTICE: Raw codes MUST BE CHANGED if your raw code has changed as indicated below
constant function MS_SPELLID takes nothing returns integer
return 'A000' //raw code
endfunction
constant function MS_METEORID takes nothing returns integer
return 'h001' //raw code
endfunction
constant function MS_ATT takes nothing returns attacktype
return ATTACK_TYPE_CHAOS
endfunction
constant function MS_DAM takes nothing returns damagetype
return DAMAGE_TYPE_FIRE
endfunction
function MS_HASH takes nothing returns nothing
set udg_HASH = InitHashtable()
endfunction
function MS_DAMAGE takes integer i returns real
return 100. + i * 50
endfunction
function MS_AOE takes integer i returns real
return 300. + i * 100
endfunction
function MS_DURATION takes integer i returns real
return 3. + i * 7
endfunction
//===END OF CONFIGURABLES
function MS_FILTERDAMAGE takes nothing returns boolean
local unit u = GetFilterUnit()
if IsUnitEnemy(u, GetOwningPlayer(udg_Caster)) and GetWidgetLife(u) > 0.405 and IsUnitType(u, UNIT_TYPE_FLYING)==false then
call UnitDamageTarget(udg_Caster, u, udg_Damage, false, false, MS_ATT(), MS_DAM(), null)
endif
set u = null
return false
endfunction
function MS_METEORDEATH takes nothing returns boolean
local unit u
local integer dummyID
if GetUnitTypeId(GetTriggerUnit())==MS_METEORID() then
set u = GetTriggerUnit()
set dummyID = GetHandleId(u)
set udg_Caster = LoadUnitHandle(udg_HASH, dummyID, 1)
set udg_Damage = LoadReal(udg_HASH, dummyID, 2)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 250, Filter(function MS_FILTERDAMAGE))
call TerrainDeformRipple(GetUnitX(u), GetUnitY(u), 10000, 30, 1, 1000, 0, 0.5, 3, false)
call FlushChildHashtable(udg_HASH, dummyID)
endif
set u = null
return false
endfunction
function MS_LOOP takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tID = GetHandleId(t)
local integer dummyID
local unit u = LoadUnitHandle(udg_HASH, tID, 1)
local unit dummy
local real damage = LoadReal(udg_HASH, tID, 2)
local real AoE = LoadReal(udg_HASH, tID, 3)
local real duration = LoadReal(udg_HASH, tID, 4)
local real x = LoadReal(udg_HASH, tID, 5)
local real y = LoadReal(udg_HASH, tID, 6)
local real offset = GetRandomReal(75, AoE)
local real angle = GetRandomReal(0, 360)
local real x1
local real y1
if duration > 0 and GetWidgetLife(u) > 0.405 then
call SaveReal(udg_HASH, tID, 4, duration - 0.5)
set x1 = x + offset * Cos(angle * bj_DEGTORAD)
set y1 = y + offset * Sin(angle * bj_DEGTORAD)
set dummy = CreateUnit(GetOwningPlayer(u),MS_METEORID(), x1, y1, 0)
set dummyID = GetHandleId(dummy) //This will be used for damage
call SaveUnitHandle(udg_HASH, dummyID, 1, u) //Saves the Caster
call SaveReal(udg_HASH, dummyID, 2, damage) //Saves the damage
call SetUnitFlyHeight(dummy, 0, 1000)
call UnitApplyTimedLife(dummy, 'BTLF', 1)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_HASH, tID)
endif
set t = null
set u = null
set dummy = null
endfunction
function MS_CAST takes nothing returns boolean
local timer t
local unit u
local integer tID
local integer level
if GetSpellAbilityId()==MS_SPELLID() then
set t = CreateTimer()
set tID = GetHandleId(t)
set u = GetTriggerUnit()
set level = GetUnitAbilityLevel(u, MS_SPELLID())
call SaveUnitHandle(udg_HASH, tID, 1, u)
call SaveReal(udg_HASH, tID, 2, MS_DAMAGE(level))
call SaveReal(udg_HASH, tID, 3, MS_AOE(level))
call SaveReal(udg_HASH, tID, 4, MS_DURATION(level))
call SaveReal(udg_HASH, tID, 5, GetUnitX(u))
call SaveReal(udg_HASH, tID, 6, GetUnitY(u))
call TimerStart(t, 0.5, true, function MS_LOOP)
endif
set t = null
return false
endfunction
function InitTrig_MeteorShower takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t1, Condition(function MS_CAST))
call TriggerAddCondition(t2, Condition(function MS_METEORDEATH))
set t1 = null
set t2 = null
call MS_HASH()
endfunction
EVENT_UNIT_DAMAGED
you use EVENT_UNIT_ATTACKED
. That's funny. You must've typed this up in a hurry. If you change it the evasion seems to work properly, but lethal damage still isn't prevented.To prevent death when the attack is fatal just add the ability 'Invu' to the unit in the event and then run a 0 second timer and remove the ability when the timer expires. Problem solved![]()
The caster creates an icy orb, which slowly moves in the direction it is cast. The orb will constantly emit ice shards which travel away from the orb. A unit hit with an ice shard is slowed for 3 seconds. The orb lasts 3 seconds. This is a diablo 2 spell, it is used by the sorceress character View attachment 102309 The original spell from Diablo 2 View attachment 102310 My version of the spell
|
looks fine, though I love the Frozen Orb made by Eccho more... ^_^
scope ThousandNeedles
// 1,000 Needles
// Made by emjlr3 for THN Spell Contest #20
// Requires nothing other than this script.
//CONFIG. FUNCTIONS:
//============================================================================
private function Buffer takes integer lvl returns real
return 25. // buffer mana required to continue channeling
endfunction
private function Cost takes integer lvl returns real
return 25. // mana cost per second
endfunction
private function Count takes integer lvl returns integer
return 100 // needles spawned per second
endfunction
private function Damage takes integer lvl returns real
return 1. // on collision
endfunction
private function Radius takes integer lvl returns real
return 100. // aoe circle radius to target
endfunction
private function Range takes integer lvl returns real
return 105. // collision size of needles
endfunction
//CONFIG. GLOBALS:
//============================================================================
globals
constant boolean PIERCE = true // needles pierce targets?
constant boolean TEXTAG = true // create damage texttags?
constant boolean TREES = true // kill trees?
endglobals
private struct needles
static constant attacktype ATTACK = ATTACK_TYPE_CHAOS // damage attacktype
static constant damagetype DAMAGE = DAMAGE_TYPE_UNIVERSAL // damage damagetype
static constant integer ABIL = 'NEED' // 1000 Needles ability id
static constant integer ORDER = 852089 // channel order id
static constant integer DUMMY = 'n000' // projectile dummy unit id
static constant integer FLYTRICK = 'Amrf' // crow form ability id
static constant real CTIMESCALE = 7. // caster time scale during channeling
static constant real DTIMESCALE = 1. // default caster time scale
static constant real FLYHEIGHT = 75. // needle fly height
static constant real SIZE = 1. // needle scale
static constant real TIMEOUT = .05 // periodic timer interval in seconds (movement and spawning)
static constant real VELOCITY = 600. // needle velocity per second
static constant string COLOR = "" // textag string color
static constant string DUMSFX = "Abilities\\Weapons\\BristleBackMissile\\BristleBackMissile.mdl" // needle model
static constant string HITATTACH = "chest" // attachment point for HITSFX
static constant string HITSFX = "" // model on target following a needle collision
//END CONFIG.
//============================================================================
static boolexpr TBOOL = null
static group GROUP = CreateGroup()
// you can replace this with a global hashtable if you want
// but be aware, I attach directly to caster units, and flush the data later
static hashtable HT = InitHashtable()
static real RVEL = VELOCITY*TIMEOUT
static real TWOPI = bj_PI*2.
static rect RECT = null
static timer TIMER = CreateTimer()
static unit T = null
// linked list attachment
thistype prev
thistype next
// 0=channel
// 1=needle
integer t=0
// the spell basics
unit cast
player p
unit dum
effect sfx
// setup needle
real x
real y
real xtarg
real ytarg
real ang
real cos
real sin
real dist
// group addition delay
real time=1.
// collision/movement related
trigger trig
group g
integer ticks
// requisite data
integer lvl
integer count
// the spell is called 1000 Needles, so no config. option for that
// if you really want to change the spell that much, here you go
integer total=1000 // total needles
real damage
real range
real radius
real mana
real buffer
string Sdamage
method destroy takes nothing returns nothing
if .t==0 then // channel
call GroupRemoveUnit(GROUP,.cast)
call FlushChildHashtable(HT,GetHandleId(.cast))
call SetUnitTimeScale(.cast,DTIMESCALE)
// ran out of needles or mana
if GetUnitCurrentOrder(.cast)==ORDER then
call PauseUnit(.cast,true)
call IssueImmediateOrder(.cast,"stop")
call PauseUnit(.cast,false)
endif
elseif .t==1 then // needle
call FlushChildHashtable(HT,GetHandleId(.trig))
call DestroyTrigger(.trig)
call DestroyEffect(.sfx)
//call KillUnit(.dum)
// usually you can't remove the unit and still get the sfx death animation to play
// in this case I can
// also, this produced much less lag, and when you have so many at once
// its a welcome boost
call RemoveUnit(.dum)
static if PIERCE then
call ReleaseGroup(.g)
endif
endif
set .prev.next=.next
set .next.prev=.prev
set .prev=0
call .deallocate()
endmethod
static method updateList takes thistype this returns nothing
set thistype(0).next.prev=this
set .next=thistype(0).next
set thistype(0).next=this
set .prev=thistype(0)
endmethod
static method treeBool takes nothing returns boolean
if GetDestructableLife(GetFilterDestructable())>0. then
call KillDestructable(GetFilterDestructable())
endif
return false
endmethod
static method onCollision takes nothing returns boolean
local thistype this=LoadInteger(HT,GetHandleId(GetTriggeringTrigger()),0)
local boolean b=true
local texttag tt
set T=GetTriggerUnit()
static if PIERCE then
set b=not IsUnitInGroup(T,.g)
endif
if UnitAlive(T) and IsUnitEnemy(T,.p) and b then
// by using dum as the damager, if you are far enough away
// the targets can't fight back, and instead run for the hills
// this may or may not be desireable, you can always update that here
call UnitDamageTarget(.dum,T,.damage,false,false,ATTACK,DAMAGE,null)
// too many sfx!!! i like it better without any
if HITSFX!="" then
call DestroyEffect(AddSpecialEffectTarget(HITSFX,T,HITATTACH))
endif
// stupid texttag limit!!!
static if TEXTAG then
// if you want to edit the texttag intricacies, do so here
set tt=CreateTextTag()
call SetTextTagText(tt,.Sdamage,.024)
// sort of randomly, somewhere on the target
call SetTextTagPos(tt,GetUnitX(T)+GetRandomReal(-15.,15.),GetUnitY(T)+GetRandomReal(-15.,15),16.)
call SetTextTagVelocity(tt,.0,.04)
call SetTextTagVisibility(tt,true)
call SetTextTagFadepoint(tt,2.5)
call SetTextTagLifespan(tt,4.)
call SetTextTagPermanent(tt,false)
set tt=null
endif
static if PIERCE then
call GroupAddUnit(.g,T)
else
// probably don't need this to avoid further enumeration
// but for shits 'n' giggles
call DisableTrigger(.trig)
call .destroy()
endif
endif
return false
endmethod
static method createNeedle takes thistype t, real x, real y, real face returns nothing
local thistype this=thistype.allocate()
local real angle=GetRandomReal(0.,TWOPI)
local real dist=GetRandomReal(0.,t.radius)
set .cast=t.cast
set .p=t.p
set .damage=t.damage
static if TEXTAG then
set .Sdamage=COLOR+I2S(R2I(.damage))
endif
// somewhere a random polar projection out from the cast loc
// taking into consideration the radius set point
set .xtarg=x+t.dist*Cos(face)+dist*Cos(angle)
set .ytarg=y+t.dist*Sin(face)+dist*Sin(angle)
set .ang=Atan2(.ytarg-y,.xtarg-x)
set .cos=RVEL*Cos(.ang)
set .sin=RVEL*Sin(.ang)
set .dum=CreateUnit(.p,DUMMY,x+.cos,y+.sin,.ang*bj_RADTODEG)
call SetUnitScale(.dum,SIZE,SIZE,SIZE)
// just incase
call UnitAddAbility(.dum,FLYTRICK)
call SetUnitFlyHeight(.dum,FLYHEIGHT,0.)
set .sfx=AddSpecialEffectTarget(DUMSFX,.dum,"origin")
// needle
set .t=1
// makes it easy to tell when the needle reaches its destination
set .ticks=R2I(SquareRoot(Pow(.xtarg-x,2)+Pow(.ytarg-y,2))/(RVEL))
// if we want needles to travel through all targets
static if PIERCE then
set .g=NewGroup()
endif
// unitinrange triggers are fun, and remove the mundane groupenumunitsinrange overhead
// using them with trigger conditions removes the possiblity of handle stack corruption
// hashtables have given us a convenient and relatively fast way to attach our struct
set .trig=CreateTrigger()
call TriggerRegisterUnitInRange(.trig,.dum,t.range,null)
call TriggerAddCondition(.trig,Condition(function thistype.onCollision))
call SaveInteger(HT,GetHandleId(.trig),0,this)
call thistype.updateList(this)
endmethod
static method periodic takes nothing returns nothing
local thistype this=thistype(0).next
local integer i
local real r
local real face
loop
exitwhen this==0
if .t==0 then // channel
// make sure we have enough needles left to cast
// but not too many now, mind you
set .total=.total-.count
if .total<0 then
set i=.count-.total
else
set i=.count
endif
// try pushing this up higher and see the real power of the spell!
set face=GetUnitFacing(.cast)*bj_DEGTORAD
loop
exitwhen i<=0
call thistype.createNeedle(this,GetUnitX(.cast),GetUnitY(.cast),face)
set i=i-1
endloop
// it just so happens that successional casts trigger just about every PLAYER_UNIT_SPELL_XXXX there is
// so we can differentiate between first channel and subsequent channels while still channeling
// FYI, this delay should be lower than the spells cooldown
set .time=.time-TIMEOUT
if .time<=0. and not IsUnitInGroup(.cast,GROUP) then
call GroupAddUnit(GROUP,.cast)
endif
call SetUnitState(.cast,UNIT_STATE_MANA,GetUnitState(.cast,UNIT_STATE_MANA)-.mana)
// no longer channeling, not enough mana or out of needles
// I remember there was a reason I didn't usually check it like this
// and instead used an SPELL_ENDCAST event
// but can't remember now why
// might have had something to do with the order id remaining
// while a unit is stunned, or some other such nonsense
// though in this map that doesn't happen when the hero is stunned
// so meh
if GetUnitState(.cast,UNIT_STATE_MANA)<.buffer or .total<=0 or GetUnitCurrentOrder(.cast)!=ORDER then
call .destroy()
endif
elseif .t==1 then // needle
set .ticks=.ticks-1
// reached its destination
if .ticks==0 then
call .destroy()
else
// room still to go
call SetUnitX(.dum,GetUnitX(.dum)+.cos)
call SetUnitY(.dum,GetUnitY(.dum)+.sin)
static if TREES then
call MoveRectTo(RECT,GetUnitX(.dum),GetUnitY(.dum))
call EnumDestructablesInRect(RECT,TBOOL,null)
endif
endif
endif
set this=.next
endloop
// linked list is empty :(
if thistype(0).next==0 then
call PauseTimer(TIMER)
endif
endmethod
static method create takes nothing returns thistype
local thistype this=thistype.allocate()
set .cast=GetTriggerUnit()
call SaveInteger(HT,GetHandleId(.cast),0,this)
call SetUnitTimeScale(.cast,CTIMESCALE)
set .p=GetTriggerPlayer()
set .lvl=GetUnitAbilityLevel(.cast,ABIL)
set .count=R2I(Count(.lvl)*TIMEOUT)
set .damage=Damage(.lvl)
set .range=Range(.lvl)
set .radius=Radius(.lvl)
set .mana=Cost(.lvl)*TIMEOUT
set .buffer=Buffer(.lvl)
set .x=GetUnitX(.cast)
set .y=GetUnitY(.cast)
set .xtarg=GetSpellTargetX()
set .ytarg=GetSpellTargetY()
set .dist=SquareRoot(Pow(.x-.xtarg,2)+Pow(.y-.ytarg,2))
if .dist<=0. then
set .dist=100.
endif
// channel
set .t=0
// linked list is empty :)
if thistype(0).next==0 then
call TimerStart(TIMER,TIMEOUT,true,function thistype.periodic)
endif
call thistype.updateList(this)
return this
endmethod
static method conditions takes nothing returns boolean
local thistype this
if GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_CHANNEL then
if GetSpellAbilityId()==ABIL and not IsUnitInGroup(GetTriggerUnit(),GROUP) then
call thistype.create()
endif
elseif GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_EFFECT then
if GetSpellAbilityId()==ABIL and IsUnitInGroup(GetTriggerUnit(),GROUP) then
set this=LoadInteger(HT,GetHandleId(GetTriggerUnit()),0)
set .dist=SquareRoot(Pow(GetUnitX(.cast)-GetSpellTargetX(),2)+Pow(GetUnitY(.cast)-GetSpellTargetY(),2))
if .dist<=0. then
set .dist=100.
endif
endif
elseif GetIssuedOrderId()!=ORDER and IsUnitInGroup(GetTriggerUnit(),GROUP) then
//call BJDebugMsg(I2S(GetIssuedOrderId()))
set this=LoadInteger(HT,GetHandleId(GetTriggerUnit()),0)
call .destroy()
endif
return false
endmethod
static method onInit takes nothing returns nothing
local trigger trig=CreateTrigger()
local integer index=0
loop
call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_SPELL_CHANNEL,null)
call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
// to my suprise learning an ability fires a unit event, and each ability has a unique learn id
// otherwise this might be full proof
//call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_ORDER,null)
//call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
//call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER,null)
//call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER,null)
set index=index+1
exitwhen index==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(trig,Condition(function thistype.conditions))
static if TREES then
// lets assume the range settings don't change, or atleast don't change much
set index=R2I(Range(1))
set RECT=Rect(-index,-index,index,index)
set TBOOL=Condition(function thistype.treeBool)
endif
endmethod
endstruct
endscope