Mine (Bomb) Spell help please

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
I have a number of issues. First and foremost I want this MUI and MPI. It needs to be spammable. Current Trigger below.
[del]a. I've been trying to remove the BJ's. There are still some in there but I've gotten tired today. I'll look at them later.[/del] Done
1. Is the spell Mui?
2. For some reason it doesn't damage any mines that are laid next to it, but it does effect all other units. The unit being created is a custom unit based off Goblin Mine. I want to be able to set off chain reactions.
3. Hows my Jassing? Give me feedback please. I want to improve.
3b. I'm having trouble with those TriggerSleepActions. I've looked into timers but I'm finding my brain has shut off and I can't concentrate enough to get the timer ideas.
4. I'm trying to head this into structs. Would someone be kind enough to guide me to that?
[del]5. I'm trying to allow for 5 different mines. Should I just make separate function for each one or is it possible to do conditions and variables that change depending on what ability is cast and what units are to be created?[/del] Done
Current Trigger
JASS:
//-------Mine Spells Integer Block
constant function ProxRawCode takes nothing returns integer
    return 'A00Z' //Proximity Mine Spell
endfunction
constant function FoFRawCode takes nothing returns integer
    return 'A011' //FoF Mine Spell
endfunction
constant function HomeRawCode takes nothing returns integer
    return 'A012' //Homing Mine Spell
endfunction
constant function StealthRawCode takes nothing returns integer
    return 'A014' //Stealth Mine Spell
endfunction
constant function AcidRawCode takes nothing returns integer
    return 'A015' //Acid Mine Spell
endfunction

function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    if ((GetSpellAbilityId()==ProxRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 1
        return GetSpellAbilityId()==ProxRawCode()
    endif
    if ((GetSpellAbilityId()==FoFRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 2
        return GetSpellAbilityId() == FoFRawCode()
    endif
    if ((GetSpellAbilityId()==HomeRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 3
        return GetSpellAbilityId()==HomeRawCode()
    endif
    if ((GetSpellAbilityId()==StealthRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 4
        return GetSpellAbilityId()==StealthRawCode()
    endif
    if ((GetSpellAbilityId()==AcidRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 5
        return GetSpellAbilityId()==AcidRawCode()
    endif
    return false
endfunction

//--------Mine Units
function MineID takes nothing returns integer
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 1 then
        return 'n003'  //Proximity Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 2 then
        return 'n005'  //FoF Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 3 then
        return 'n002'  //Homing Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 4 then
        return 'n000'  //Stealth Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 5 then
        return 'n004'  //Acid Mine Spell
    endif
return 0
endfunction

//-------Generic Mine stuff
constant function MineFuse takes nothing returns real
    return 6.
endfunction

constant function MineBlastRadius takes nothing returns real
    return 200. //Mine Blast Radius
endfunction

constant function MineDamage takes nothing returns real
    return 300. //Proximity Mine Damage
endfunction

function Trig_CreateProximityMineJass2_Actions takes nothing returns nothing
   local unit Caster = GetTriggerUnit()
   local real CasterX = GetUnitX(Caster)
   local real CasterY = GetUnitY(Caster)
   local real CasterFace = GetUnitFacing(Caster)
   local unit Mine
   local unit Explosion

   set Mine = CreateUnit(GetOwningPlayer(Caster), MineID(), CasterX, CasterY, bj_UNIT_FACING)
   call UnitApplyTimedLife(Mine ,'BTLF', MineFuse())
   call TriggerSleepAction(MineFuse())

   set Explosion = CreateUnit(GetOwningPlayer(Caster),'h00Q',GetUnitX(Mine),GetUnitY(Mine),bj_UNIT_FACING)
   call UnitDamagePoint(Mine, 0, MineBlastRadius(), GetUnitX(Mine), GetUnitY(Mine), MineDamage(), true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
   call UnitApplyTimedLife(Explosion, 'BTLF', 2)
   
   set Caster            = null
   set Mine              = null
   set Explosion         = null
   
endfunction

//===========================================================================
function InitTrig_CreateProximityMineJass2 takes nothing returns nothing
    set gg_trg_CreateProximityMineJass2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CreateProximityMineJass2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_CreateProximityMineJass2, Condition( function Trig_CreateProximityMineJass2_Conditions ) )
    call TriggerAddAction( gg_trg_CreateProximityMineJass2, function Trig_CreateProximityMineJass2_Actions )
endfunction


*Edit: Removed the old triggers.
 
I've decided that my triggering suxxors and I'm redoing it.

Sinners: wouldn't your Jass make a unit every time I use that Mine Variable? I don't want to make one every time.
 
If this is going to be submitted in the spell zone, here is an optimized version:
JASS:
constant function RawCode takes nothing returns integer
    return 'A00Z'
endfunction
constant function MineTimer takes nothing returns real
    return 6.
endfunction
constant function MineBlastRadius takes nothing returns real
    return 500.
endfunction
constant function MineDamage takes nothing returns real
    return 300.
endfunction
constant function MineID takes nothing returns integer
    return 'n003'
endfunction

function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == RawCode() 
endfunction

function Trig_CreateProximityMineJass2_Actions takes nothing returns nothing

    local unit Caster = GetTriggerUnit()
    local integer CasterID = GetUnitTypeId(Caster)
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local real CasterFace = GetUnitFacing(Caster)
    local unit Mine
    local unit Explosion
    
   set Mine = call CreateUnit(GetOwningPlayer(Caster), MineID(), CasterX, CasterY, bj_UNIT_FACING)
   call UnitApplyTimedLife(Mine,'BTLF', MineTimer())
   call TriggerSleepAction(MineTimer())

   set Explosion = call CreateUnit(GetOwningPlayer(Caster),'Ekee',CasterX,CasterY,bj_UNIT_FACING)
   call UnitDamagePoint(Mine, 0, MineBlastRadius(), CasterX, CasterY, MineDamage(), true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
   call TriggerSleepAction(2)
   call RemoveUnit(Explosion)
   
   set Caster            = null
   set Mine              = null
   set Explosion         = null
   
endfunction

//===========================================================================
function InitTrig_CreateProximityMineJass2 takes nothing returns nothing
    set gg_trg_CreateProximityMineJass2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CreateProximityMineJass2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_CreateProximityMineJass2, Condition( function Trig_CreateProximityMineJass2_Conditions ) )
    call TriggerAddAction( gg_trg_CreateProximityMineJass2, function Trig_CreateProximityMineJass2_Actions )
//    call ExecuteFunc("Trig_CreateProximityMineJass2_Actions")
endfunction


If it is personal, just inline the constant functions. If you need me to explain any of this, I will gladly do so. :)
 
Thanks for doing that Purge. There are errors though.

Need to remove call in both of these lines.
JASS:
set Mine = call CreateUnit(GetOwningPlayer(Caster), MineID(), CasterX, CasterY, bj_UNIT_FACING)
set Explosion = call CreateUnit(GetOwningPlayer(Caster),'Ekee',CasterX,CasterY,bj_UNIT_FACING)


These will need to change to a timer. Not TriggerSleepActions.
JASS:
call TriggerSleepAction(MineTimer())
call TriggerSleepAction(2)


I'm also toying with the idea that the explosion should be a separate function, so that any mine can call it.

This needs to have the X and Y of the mine, not the caster.
JASS:
call UnitDamagePoint(Mine, 0, MineBlastRadius(), CasterX, CasterY, MineDamage(), true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)


I realized I had forgotten these in my trigger so thanks for reminding me.
JASS:
   set Caster            = null
   set Mine              = null
   set Explosion         = null


I've had enough of a break today to realise my stupidity in the making of and posting my trigger. It was far from ready for such a move.

I do appreciate the time you took to change it though :)

Note: I don't want someone to fix all my problems in this script. I'd like someone to point out a mistake and help me understand what I did wrong so that I can learn. I want to become better at scripting, not just have someone fix everything i do.
 
Note: I don't want someone to fix all my problems in this script. I'd like someone to point out a mistake and help me understand what I did wrong so that I can learn. I want to become better at scripting, not just have someone fix everything i do.
JASS:
local unit Caster = GetSpellAbilityUnit()
//change to
local unit Caster = GetTriggerUnit()


JASS:
call CreateNUnitsAtLoc(1, 'Ekee', GetTriggerPlayer(), GetUnitLoc(Mine), bj_UNIT_FACING)
   set Explosion = GetLastCreatedUnit()
//change to
set Explosion = CreateNUnitsAtLoc(1, 'Ekee', GetTriggerPlayer(), GetUnitLoc(Mine), bj_UNIT_FACING)
//also for the mine unit


JASS:
//also you can avoid trigger sleep actions, and change them to
call UnitApplyTimedLife(Explosion, 2.0)


and lastly nullifying local triggers
 
JASS:
//also you can avoid trigger sleep actions, and change them to
call UnitApplyTimedLife(Explosion, 2.0)

Thanks for all that.
I can only do that on the explosion unit. If I do this on the mine unit the explosion unit gets created instantly. I need a timer or an attachment thing. I don't want to use HandleVars or GC. I want to use something faster because there will be hella movement and stuff on my map.

*Updated first post with current trigger. Thanks to Purge and Waaks so far.
 
Don't know how to yet. I started down that road about a week or two ago.
I think ABC or Vex's thingy is what I need but I'm not sure.
 
SetCSData() and GetCSData() along with a timer works very well, those functions are included in CSCache.

JASS:
struct dastruct
    unit caster
    real somenumber
    etc.
endstruct

function timer_func takes nothing returns nothing
local dastruct dat = GetCSData(GetExpiredTimer())
local unit caster = dat.caster
local real somenumber = dat.somenumber

//

call dat.destroy()
endfunction

function main takes nothing returns nothing
local unit caster
local real somenumber
local dastruct dat = dastruct.create()
local timer t = CreateTimer()

set dat.caster = caster
set dat.somenumber = somenumber
call SetCSData(t,dat)

call TimerStart(t,1.00,false, function timer_func)
set caster = null
endfunction


That's how you can pass objects to another function using a timer (which is 1000000 times more accurate than TriggerSleepAction or PolledWait).
 
Where can I find some more info on that? I need to read up on it. Isnt this part of handle vars?
 
Where can I find some more info on that? I need to read up on it. Isnt this part of handle vars?

Handle vars, use Gamecaches, stuff used in Save/load systems and more. Basically, it stores that variable, then you can retrieve it in the next function using StoreInteger/GetStoredInteger. This lets you use it in different functions. The handle vars, let you do this.

Structs, though, are faster and more efficient in cases. If you know only basic JASS, I suggest you can learn handle vars if you want to, but you should use structs.. After you've gone away from the handle var phase.

Also, do you still have the old code? If you want, I can explain my code better if you post it.. I didn't save the .j, I just c'n'p, edited, then c'n'p back to the post.
 
Structs, though, are faster and more efficient in cases. If you know only basic JASS, I suggest you can learn handle vars if you want to, but you should use structs.. After you've gone away from the handle var phase.

Also, do you still have the old code? If you want, I can explain my code better if you post it.. I didn't save the .j, I just c'n'p, edited, then c'n'p back to the post.

I'd like to use structs. Handle vars? I'm over them. ;)
I understood your code. I've basically used yours and modified it further. You took mine and made it better, I took yours and made it better, and now together we shall rule the worl....sorry carried away there.

If you can help me get structs into this spell for the timer I'll give you a donut. Or if you can help me convert the entire thing to structs I'll give you two donuts.

See the current code in the spoiler in the first post.
 
Note: Deliberate double post as the my last post isn't really related to anything...really.

[del] How do I write this correctly? It tells me the endif at the bottom is "Missing Return"[/del] Nevermind. I got it.
JASS:
function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    if (GetSpellAbilityId() == ProxRawCode())==true then
        return GetSpellAbilityId() == ProxRawCode()
    elseif (GetSpellAbilityId() == FoFRawCode())==true then
        return GetSpellAbilityId() == FoFRawCode()
    elseif (GetSpellAbilityId() == HomeRawCode())==true then
        return GetSpellAbilityId() == HomeRawCode()
    elseif (GetSpellAbilityId() == StealthRawCode())==true then
        return GetSpellAbilityId() == StealthRawCode()
    elseif (GetSpellAbilityId() == AcidRawCode())==true then
        return GetSpellAbilityId() == AcidRawCode()
    endif
endfunction

(Gui Conversion with tweaking - Is there a better way?)
JASS:
function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    if ((GetSpellAbilityId()==ProxRawCode())) then
        return GetSpellAbilityId()==ProxRawCode()
    endif
    if ((GetSpellAbilityId()==StealthRawCode())) then
        return GetSpellAbilityId()==StealthRawCode()
    endif
    if ((GetSpellAbilityId()==HomeRawCode())) then
        return GetSpellAbilityId()==HomeRawCode()
    endif
    if ((GetSpellAbilityId()==FoFRawCode())) then
        return GetSpellAbilityId()==FoFRawCode()
    endif
    if ((GetSpellAbilityId()==AcidRawCode())) then
        return GetSpellAbilityId()==AcidRawCode()
    endif
    return false
endfunction

The below is spitting out an error message of:
"Comparing two variables of different primitives (except Real and Integer is not allowed)"
So what do I need to do to convert the Boolean (above Jass) to Integer (the below?)
JASS:
function MineID takes nothing returns integer
//    return 'n003'
    if ( (Trig_CreateProximityMineJass2_Conditions == ProxRawCode())==true ) then
        return 'n003'
    endif
    if ( ( Trig_CreateProximityMineJass2_Conditions == StealthRawCode() ) ) then
        return 'n003'
    endif
    if ( ( Trig_CreateProximityMineJass2_Conditions == HomeRawCode() ) ) then
        return 'n003'
    endif
    if ( ( Trig_CreateProximityMineJass2_Conditions == FoFRawCode() ) ) then
        return 'n003'
    endif
    if ( ( Trig_CreateProximityMineJass2_Conditions == AcidRawCode() ) ) then
        return 'n003'
    endif

endfunction
 
this depends on what the functions on the first trigger returns if they return integer it should work
and btw when you do something like this:
JASS:
    if ((GetSpellAbilityId()==ProxRawCode())) then
        return GetSpellAbilityId()==ProxRawCode()
    endif

it's pointless to return the same thing as you did on the 'if' since you already checked so it would simply be easier to just put return true like this:
JASS:
    if ((GetSpellAbilityId()==ProxRawCode())) then
        return true
    endif
 
Whatever happened to people actually reading the posts? ;)

this depends on what the functions on the first trigger returns if they return integer it should work
and btw when you do something like this:
JASS:
    if ((GetSpellAbilityId()==ProxRawCode())) then
        return GetSpellAbilityId()==ProxRawCode()
    endif

it's pointless to return the same thing as you did on the 'if' since you already checked so it would simply be easier to just put return true like this:
JASS:
    if ((GetSpellAbilityId()==ProxRawCode())) then
        return true
    endif

You are correct, however the first trigger returns a boolean. It is the "spell is casted condition check". I wrote it that way because of this next Jass...the shortened way to do the conditioning. I just replaced "true" with the coding.

JASS:
function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
        return GetSpellAbilityId()==ProxRawCode()
endfunction


I need some way of saying (if stealth spell is cast then use the stealth unit Integer). I'm wondering if I could set a LastCreatedMineUnit[PlayerNumber] global variable of some sort so that when it stealth is cast, it will change the triggering players last mine variable to stealth. Then if the mine variable == stealth mine then use the stealth unit integer.

Make sense?
 
YOUR A GENIUS DOOM! I love the way your being a bouncing board works :).

Current working trigger. Updated first post.
JASS:
//-------Mine Spells Integer Block
constant function ProxRawCode takes nothing returns integer
    return 'A00Z' //Proximity Mine Spell
endfunction
constant function FoFRawCode takes nothing returns integer
    return 'A011' //FoF Mine Spell
endfunction
constant function HomeRawCode takes nothing returns integer
    return 'A012' //Homing Mine Spell
endfunction
constant function StealthRawCode takes nothing returns integer
    return 'A014' //Stealth Mine Spell
endfunction
constant function AcidRawCode takes nothing returns integer
    return 'A015' //Acid Mine Spell
endfunction

function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    if ((GetSpellAbilityId()==ProxRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 1
        return GetSpellAbilityId()==ProxRawCode()
    endif
    if ((GetSpellAbilityId()==FoFRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 2
        return GetSpellAbilityId() == FoFRawCode()
    endif
    if ((GetSpellAbilityId()==HomeRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 3
        return GetSpellAbilityId()==HomeRawCode()
    endif
    if ((GetSpellAbilityId()==StealthRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 4
        return GetSpellAbilityId()==StealthRawCode()
    endif
    if ((GetSpellAbilityId()==AcidRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 5
        return GetSpellAbilityId()==AcidRawCode()
    endif
    return false
endfunction

//--------Mine Units 
function MineID takes nothing returns integer
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 1 then
        return 'n003'  //Proximity Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 2 then
        return 'n005'  //FoF Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 3 then
        return 'n002'  //Homing Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 4 then
        return 'n000'  //Stealth Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 5 then
        return 'n004'  //Acid Mine Spell
    endif
return 0
endfunction

//-------Generic Mine stuff
constant function MineFuse takes nothing returns real
    return 6.
endfunction

constant function MineBlastRadius takes nothing returns real
    return 200. //Mine Blast Radius
endfunction

constant function MineDamage takes nothing returns real
    return 300. //Proximity Mine Damage
endfunction

function Trig_CreateProximityMineJass2_Actions takes nothing returns nothing
   local unit Caster = GetTriggerUnit()
   local real CasterX = GetUnitX(Caster)
   local real CasterY = GetUnitY(Caster)
   local real CasterFace = GetUnitFacing(Caster)
   local unit Mine
   local unit Explosion

   set Mine = CreateUnit(GetOwningPlayer(Caster), MineID(), CasterX, CasterY, bj_UNIT_FACING)
   call UnitApplyTimedLife(Mine ,'BTLF', MineFuse())
   call TriggerSleepAction(MineFuse())

   set Explosion = CreateUnit(GetOwningPlayer(Caster),'h00Q',GetUnitX(Mine),GetUnitY(Mine),bj_UNIT_FACING)
   call UnitDamagePoint(Mine, 0, MineBlastRadius(), GetUnitX(Mine), GetUnitY(Mine), MineDamage(), true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
   call UnitApplyTimedLife(Explosion, 'BTLF', 2)
   
   set Caster            = null
   set Mine              = null
   set Explosion         = null
   
endfunction

//===========================================================================
function InitTrig_CreateProximityMineJass2 takes nothing returns nothing
    set gg_trg_CreateProximityMineJass2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CreateProximityMineJass2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_CreateProximityMineJass2, Condition( function Trig_CreateProximityMineJass2_Conditions ) )
    call TriggerAddAction( gg_trg_CreateProximityMineJass2, function Trig_CreateProximityMineJass2_Actions )
endfunction
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top