| 08-17-2008, 01:04 PM | #1 |
Hi, This is my first time entering a competition on wc3c, so I'm interested in opinions/improvements on my coding. I've spent a good three or four days working on this, so I hope it isn't too bad: JASS:scope PSphere initializer Init //=========================================================================================================\\ //==================================================Info===================================================\\ //=========================================================================================================\\ // \\ // |Pressure Sphere| by saw792 (TheHelper, wc3campaigns) \\ // ------------------------- \\ // Creates a concentrated ball of air at the location of the caster, briefly stunning all units \\ // in the AOE and causing the caster to be propelled backwards through the air. \\ // \\ // Requires: \\ // --------- \\ // - A vJASS preprocessor (Jasshelper, Newgen Pack) \\ // - CSData from Caster System (by Vexorian) \\ // \\ // To use in your own map: \\ // ----------------------- \\ // - Copy this text into a blank GUI trigger converted to custom text \\ // - Copy the 'Dummy' unit from the object editor into your map \\ // - Give the ability to a hero, and enjoy \\ // \\ // \\ //=========================================================================================================\\ //=================================================Globals=================================================\\ //=========================================================================================================\\ globals private unit caster //Casting unit private boolean cancel = false //Don't change. Used in conjunction with ALLOWCANCEL private constant real TOTAL_TIME = 1.5 //Total length of spell. Modify this value rather than T //Must be greater than T at all times. private constant real TIMER_INTERVAL = 0.04 //Number of seconds between timer expirations private constant integer ABILITY_ID = 'A000' //Rawcode of Pressure Sphere Ability //SFX config globals private constant integer DUMMY_ID = 'h000' //Rawcode of SFX dummy unit private constant real T = 1.2 //Knockback time and SFX dummy grow time. Modification not recommended. private constant real MAX_SCALE = 8 //Largest unit scale SFX dummy reaches. Initial scale should always be 1. //Knockback config globals private constant real S = 200 //Distance of knockback private constant real A = 555.5556 //Rate of deceleration of knockback private constant real RADIUS = 250 //AOE of knockback effect from caster //Jump config globals private constant boolean ALLOWCANCEL = true //Set this to true to allow the caster to cancel the slide private constant real JUMP_DISTANCE = 600 //Distance travelled in jump in a straight line (no height) private constant real MAX_HEIGHT = 300 //Max height reached in the jump endglobals //=========================================================================================================\\ //=================================================Structs=================================================\\ //=========================================================================================================\\ private struct Sphere //Miscellaneous integer tcount real exit1 = TOTAL_TIME / TIMER_INTERVAL real exit2 = T / TIMER_INTERVAL //SFX unit dummy real x real y real scale real scaleminus = (MAX_SCALE - 1) / (.exit1-.exit2) real scaleplus = (MAX_SCALE-1) / .exit2 //Knockback real rs = -S + 400 //Correcting for distance offset real ns real u real dx real dy real a unit target group g = CreateGroup() group gcopy = CreateGroup() //Jump real jx real jy real jz real ja real jd real cosj real sinj static method create takes nothing returns Sphere local Sphere data = Sphere.allocate() set caster = GetTriggerUnit() set data.x = GetUnitX(caster) set data.y = GetUnitY(caster) set data.scale = 1.00 set data.dummy = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, data.x, data.y, 0) set data.ja = ((GetUnitFacing(caster) * bj_DEGTORAD) - 3.1416) //The opposite direction set data.jd = (JUMP_DISTANCE / data.exit1) //Distance per execution set data.cosj = Cos(data.ja) set data.sinj = Sin(data.ja) call UnitAddAbility(caster, 'Arav') return data endmethod method onDestroy takes nothing returns nothing call RemoveUnit(.dummy) call DestroyGroup(.gcopy) call SetUnitFlyHeight(caster, 0, 0) call UnitRemoveAbility(caster, 'Arav') set cancel = false set caster = null endmethod endstruct //=========================================================================================================\\ //===============================================Functions=================================================\\ //=========================================================================================================\\ private function Conditions takes nothing returns boolean return GetSpellAbilityId() == ABILITY_ID and ALLOWCANCEL endfunction private function MoveCancelConditions takes nothing returns boolean return GetIssuedOrderId() == OrderId("smart") endfunction private function FilterG takes nothing returns boolean return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(caster)) endfunction private function Unpause takes nothing returns nothing call PauseUnit(GetEnumUnit(), false) endfunction private function Callback takes nothing returns nothing local timer t = GetExpiredTimer() local Sphere data = GetCSData(t) call GroupAddGroup(data.g, data.gcopy) set data.tcount = data.tcount + 1 //SFX if data.tcount > data.exit1 then //When SFX and Knockback end call ForGroup(data.g, function Unpause) call PauseTimer(t) call DestroyTimer(t) set data.tcount = 0 call data.destroy() else if data.tcount >= data.exit2 then set data.scale = data.scale - data.scaleminus call SetUnitScale(data.dummy, data.scale, data.scale, data.scale) else set data.scale = data.scale + data.scaleplus call SetUnitScale(data.dummy, data.scale, data.scale, data.scale) endif //Knockback set data.rs = data.rs - data.ns //Distance remaining to travel set data.u = (data.rs - 0.5 * A * T * T) / T //s = ut + 1/2at^2 rearranged for u set data.ns = (data.u * TIMER_INTERVAL + 0.5 * A * TIMER_INTERVAL * TIMER_INTERVAL) //Distance to travel this interval. Once again uses loop //s = ut + 1/2at^2 set data.target = FirstOfGroup(data.gcopy) exitwhen data.target == null set data.a = (Atan2(data.y - GetUnitY(data.target), data.x - GetUnitX(data.target))) //Angle between caster and target unit set data.dx = (data.ns * Cos(data.a) + GetUnitX(data.target)) //Old horizontal position + horizontal distance to move set data.dy = (data.ns * Sin(data.a) + GetUnitY(data.target)) //Old vertical position + vertical distance to move call PauseUnit(data.target, true) call SetUnitPosition(data.target, data.dx, data.dy) call GroupRemoveUnit(data.gcopy, data.target) endloop //Jump set data.jx = (data.tcount * data.jd * data.cosj + data.x) //Another polar projection set data.jy = (data.tcount * data.jd * data.sinj + data.y) //Another polar projection set data.jz = (-(MAX_HEIGHT / ((data.exit1 / 2) * (data.exit1 / 2))) * data.tcount) * (data.tcount - data.exit1) //Quadratic relationship if cancel == false then call SetUnitPosition(caster, data.jx, data.jy) endif call SetUnitFlyHeight(caster, data.jz, 0) endif endfunction private function MoveCancel takes nothing returns nothing if caster != null then set cancel = true endif endfunction private function Actions takes nothing returns nothing local Sphere data = Sphere.create() local timer t = CreateTimer() call GroupEnumUnitsInRange(data.g, data.x, data.y, RADIUS, Condition(function FilterG)) call SetCSData(t, data) call TimerStart(t, 0.04, true, function Callback) endfunction //=========================================================================================================\\ //===================================================Init==================================================\\ //=========================================================================================================\\ private function Init takes nothing returns nothing local trigger t = CreateTrigger() local trigger t2 = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER) call TriggerAddCondition(t, Condition(function Conditions)) call TriggerAddCondition(t2, Condition(function MoveCancelConditions)) call TriggerAddAction(t, function Actions) call TriggerAddAction(t2, function MoveCancel) set t = null set t2 = null endfunction endscope EDIT: Screenshot in Olympics thread. Also, does this comply to JESP? |
| 08-19-2008, 01:05 PM | #2 |
48hr bump |
| 08-19-2008, 02:31 PM | #3 |
I can see no obvious bad things with the code. You could use TimerUtils instead of CSData. |
| 08-20-2008, 01:04 PM | #4 | |
Quote:
Also, pausing units is lame, you should be stunning them. |
| 08-20-2008, 01:14 PM | #5 |
Umm are you sure it isn't multi-instanceable? I have a test map for it that has caused no problems with about 8 simultaneous casts from different players. Can you point out the problem areas? Levels haven't been implemented yet. Stun, ok that shall be done. |
| 08-20-2008, 02:37 PM | #6 |
The caster and cancel global variables can only work for one instance at once. |
| 08-21-2008, 06:14 AM | #7 |
Mm true... fixed now (might update it here later). Thanks Anitarf. |
