wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Tutorials > JASS/AI scripts tutorials
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 01-23-2006, 08:32 PM   #1
Blade.dk
.
 
Blade.dk's Avatar


Respected User
 
Join Date: May 2005
Posts: 1,990

Submissions (15)

Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)

Approved Map: Azeroth's Arcane ArenaSpell session 01 winner

Send a message via MSN to Blade.dk
Default Creating simple AIs for Hero Arena-type maps

NOTE: You have been redirected in order for our attachments to be made available to you. This will only last two minutes; these measures where taken to avoid hotlinking and bandwidth theft.
To avoid these restrictions Log in or Register

This tutorial will help you add a simple, but cool, AI to hero arena type maps.

The AI you’ll learn how to make here will not be perfect. The one we will create here will attack other heroes, pick up items, learn and use spells, but it won’t be as effective as a human player.

However, when you’ve learned the basics you should be able to improve it yourself.

Requires

JASS Knowledge – This tutorial uses JASS examples, and JASS-only features, so you will need to know JASS to follow this tutorial and make the AI. Technically it can be done in the GUI, but I won’t recommend that due to memory leaks, tons of unneeded code, and because using return bug and game cache based systems isn’t possible in the GUI. If you don’t know JASS, check the JASS tutorials at The JASS Vault and Wc3Campaigns.
You also need to know what a rawcode are, if you don’t, just search the different Warcraft 3 sites to find out.
A game cache and return bug based system – This can be KaTTaNa’s Local Handle Variables, Vexorian’s CSCache module (a part of the Caster System) or any other similar system.
In this tutorial I’ll use the CSCache module.
This map – A small map I’ve created that shows a simple AI like the one we’ll make in action. It is important that you have this map, as the tutorial often refers to it.

Notes
- The AI we’ll make here is not as good as a human player, but better than nothing. And when you’ve learned the basics, you should be able to improve it yourself.
- A lot of numbers (player numbers, for example) starts from 1 in the GUI, but while they starts from 0 in JASS. As this is a JASS tutorial, they start from 0 here.
- You don’t have to do the things exactly like I do them; I do it in my way, but if your way is better or you just feel more comfortable with it, do it your own way. I’m not perfect, and this tutorial isn’t perfect either, but hopefully it will help somebody.
- You could use the AI from my demo map without creating your own (if you do so, give me credit), but I suggest making your own, as maps can be very different, and because you should be able to learn more from making it yourself.
- The demo map is probably not perfectly unbugged, and it isn’t the funniest map either. Remember that it was just a map I quickly created to show a simple AI, if you want to see a better map with a good AI, take a look at Azeroth’s Arcane Arena.
- I would like to specially thank Vexorian for encouraging me to make my first AI for my map, giving me tips on how to do it, and for showing me his AI, which helped me improve mine. Thanks!

Initialization

First create a new trigger with the “Player - Player 1 (Red) leaves the game” event. Convert it to JASS. We need that trigger to register when a player leaves the game, so we can start the AI for that player. At the moment it will only register when player 0 leaves the game, so we’ll use a loop to make it register when any player from 0-11 leaves instead.

We want the AI to use abilities. This may sound hard, but it isn’t. We just have to make the Heroes learn the abilities, and they’ll cast them themselves.

NOTE: The situation where a computer-controlled hero will cast a spell is always the same situation as where it would cast the spell it’s based on. So if you have a custom spell based on Silence, it will cast it in situations where it would cast it in melee games. NEVER base your spells of the “Channel” ability, as the AI never will use them. Changing the OrderString field on a spell in the Object Editor does nothing, it will still be the same as on the base spell.

To know which spells the heroes have, we create a game cache to store it in.

In the example map my trigger creates a gamecache at map initialization and saves it in the udg_GameCache global variable. Note that the cache HAS to be initialized before we starts using it, so I will do that in the first InitTrig function of my map.

In my map I create a function called “SetupSkills”. In the AI trigger’s InitTrig function I use the ExecuteFunc native (read more about that native here) to execute that function in another thread. This is to prevent the map initialization thread from getting too long, and crash.

My SetupSkills function looks like this:

Collapse JASS:
 function SetupSkills takes nothing returns nothing
    local string h // Create a local string variable
// Paladin // Here we’ll initialise the Paladin’s skills, repeat this for all other heroes
    set h = UnitId2String('Hpal') // Store the returned value of UnitId2String(‘Hpal’) in the local
    call StoreInteger(udg_GameCache, h, "BaseSkill1", 'AHhb') // One of his base skills is Holy Light, store it as “BaseSkill1”
    call StoreInteger(udg_GameCache, h, "BaseSkill2", 'AHds') // Store Divine Shield as “BaseSkill2”
    call StoreInteger(udg_GameCache, h, "BaseSkill3", 'AHad') // Store Devotion Aura as “BaseSkill3”
    call StoreInteger(udg_GameCache, h, "UltimateSkill", 'AHre') // Store Resurrection as his “UltimateSkill”// Repeat for each Hero.
endfunction

Here’s my InitTrig_AI function:

Collapse JASS:
 function InitTrig_AI takes nothing returns nothing
    local integer i = 0
    set gg_trg_AI = CreateTrigger(  )
    loop
        exitwhen i > 11
        call TriggerRegisterPlayerEventLeave( gg_trg_AI, Player(i) )
        set i = i + 1
    endloop
    call TriggerAddAction( gg_trg_AI, function PlayerLeaves )
    call ExecuteFunc("SetupSkills")
endfunction

Starting the AI for a hero

To control the AI I will use a timer. I create a function called “StartAI” that takes a single unit argument: the hero (check the function in the example map). The function just creates a timer, "attaches" the hero to it, and starts it (just make the expiration function now, we will out some actions into it later, but you need the function and endfunction lines to prevent getting compile errors).

This is the empty AILoop function and the StartAI function from the example map:

Collapse JASS:
function AILoop takes nothing returns nothing
endfunction

function StartAI takes unit hero returns nothing
    local timer m = CreateTimer()
    call AttachObject(m, "hero", hero)
    call TimerStart(m, 0, false, function AILoop)
    set m = null
endfunction

Note that I’m starting it as a “one-shot” timer, by using false as the 'periodic' boolean value (we’ll get back to that later).

Now just make your hero selection system call that function when a computer controlled player chooses a hero, and go to the function that is executed when a player leaves the game. Check if the player has a hero, if he/she has one, call the function that starts the AI on that hero. Example:

Collapse JASS:
function PlayerLeaves takes nothing returns nothing
    local player p = GetTriggerPlayer()
    call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, GetPlayerName(p)+" has left the game.")
    if udg_Hero[GetPlayerId(p)] != null then
        call StartAI(udg_Hero[GetPlayerId(p)])
    endif
    set p = null
endfunction

NOTE: This will make the AI take control of a leaving player's hero, this is not needed, if you want to do something else when a player leaves.

Making the AI do something

Whenever the timer expires there are some things we want it to do:
  • If the hero is dead, wait until he/she/it is revived.
  • If the hero is about to die, order him/her/it to move to the fountain at the map center.
  • If the hero has a fine amount of health, check if an enemy is close. If true, order the Hero to attack it, else check for items close to the hero, if any, issue a smart order so the Hero will pick the up. if there isn’t any, just order the hero to patrol to a random point in the arena.
  • If the hero is alive and has any unused skill points, learn a skill.

We’ll start with declaring all the variables. Notice the real variable 'e' in my function, it defines how long time will elapse before the timer expires again, so we can wait shorter time if the hero is dead, or longer time if he/she/it is attacking. That variable is initialized with the value 5.

Declare the local variables:

Collapse JASS:
function AILoop takes nothing returns nothing
    local string a = GetAttachmentTable(GetExpiredTimer())
    local unit h = GetTableUnit(a, "hero")
    local rect i
    local location r
    local real x = GetUnitX(h)
    local real y = GetUnitY(h)
    local group g
    local boolexpr b
    local boolexpr be
    local unit f
    local string o = OrderId2String(GetUnitCurrentOrder(h))
    local real l = GetUnitState(h, UNIT_STATE_LIFE)
    local real e = 5

We start with checking if the hero is dead, if he/she/it is, set the real variable to 1.5 (because waiting 5 seconds after revival is too long time, we don’t want that).

The hero’s life ('l' is 0, just set e to 1.5 to make the timer check more frequently for the hero’s revival.

Collapse JASS:
if l <= 0 then
        set e = 1.5
    endif

Next I check if the hero’s life is below 20% of it's max life. If it is low, order the hero to move to fountain and set the variable 'e' to 3.

The hero’s life is less than 20% of max life, so order the hero to move to the position of the fountain:

Collapse JASS:
if l < GetUnitState(h, UNIT_STATE_MAX_LIFE)/5 then
        call IssuePointOrder(h, "move", GetUnitX(gg_unit_nfoh_0001), GetUnitY(gg_unit_nfoh_0001))
        set e = 3

If the hero isn’t weak, check if he/she/it has a common order (to prevent it from interrupting channel spells). If it is a standard order, we check if any enemies are within a radius of 500. If true, simply issue an attack order (don’t change the 'e' variable, 5 seconds is fine in this situation).

Collapse JASS:
 function AIFilterEnemyConditions takes nothing returns boolean
    return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0 and IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetAttachedUnit(GetExpiredTimer(), "hero")))
endfunctionelse
        if ((o == "smart") or (o == "attack") or (o == "patrol") or (o == "move") or (o == "stop") or (o == "hold") or (o == null)) then
            set g = CreateGroup()
            set b = Condition(function AIFilterEnemyConditions)
            call GroupEnumUnitsInRange(g, x, y, 500, b)
            set f = FirstOfGroup(g)
            if f == null thenelse
                call IssueTargetOrder(h, "attack", f)
            endif
            call DestroyGroup(g)
            call DestroyBoolExpr(b)
        endif


If no enemies are found, check for items. If an item is found, check if it’s a powerup. If it isn’t, check if the hero has any empty inventory slots, and order the hero to pick it up.

Collapse JASS:
 function AISetItem takes nothing returns nothing
    set bj_lastRemovedItem=GetEnumItem()
endfunction

function AIItemFilter takes nothing returns boolean
    return IsItemVisible(GetFilterItem()) and GetWidgetLife(GetFilterItem()) > 0
endfunction

function AIHasEmptyInventorySlot takes unit u returns boolean
    return UnitItemInSlot(u, 0) == null or UnitItemInSlot(u, 1) == null or UnitItemInSlot(u, 2) == null or UnitItemInSlot(u, 3) == null or UnitItemInSlot(u, 4) == null or UnitItemInSlot(u, 5) == null
endfunctionif f == null then
                set i = Rect(x-800, y-800, x+800, y+800)
                set be = Condition(function AIItemFilter)
                set bj_lastRemovedItem=null
                call EnumItemsInRect(i, be, function AISetItem)
                if bj_lastRemovedItem != null and (GetItemType(bj_lastRemovedItem) == ITEM_TYPE_POWERUP or AIHasEmptyInventorySlot(h)) then
                    call IssueTargetOrder(h, "smart", bj_lastRemovedItem)
                elseendif
                call RemoveRect(i)
                call DestroyBoolExpr(be)
…

If the hero has items in all slots, or no items existed, order him/her/it to patrol to a random location in the map, to find new targets.

Collapse JASS:
else
                    set r = GetRandomLocInRect(bj_mapInitialPlayableArea)
                    call IssuePointOrderLoc(h, "patrol", r)
                    call RemoveLocation(r)
…

Now let’s check if the hero has any unused skill points (keep this separated from the attack/item pickup/patrol block).

If he/she/it has, call a function that learns a skill to the hero. In my example I’ve used a function that stores the number it has taught the hero an ability, to keep a special pattern in the ability learning:

Collapse JASS:
function AILearnSkill takes unit h, string a returns nothing
    local integer i = GetTableInt(a, "LearnSkillOrder")+1
    if i == 1 or i == 4 or i == 8 then
        call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), "BaseSkill1"))
    elseif i == 2 or i == 5 or i == 9 then
        call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), "BaseSkill2"))
    elseif i == 3 or i == 7 or i == 10 then
        call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), "BaseSkill3"))
    elseif i == 6 then
        call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), "UltimateSkill"))
    endif
    call SetTableInt(a, "LearnSkillOrder", i)
endfunctionif GetHeroSkillPoints(h) > 0 and l > 0 then
        call AILearnSkill(h, a)
    endif

Now simply make the timer expire again after 'e' seconds:

Collapse JASS:
call TimerStart(GetExpiredTimer(), e, true, function AILoop)
…

Last we need to set the local variables to null:

Collapse JASS:
set h = null
    set i = null
    set r = null
    set g = null
    set b = null
    set f = null
    set be = null

Final notes

This is the basics of it, it can be way better, but this should help you get started. Feel free to ask questions here or pm me.

It shouldn’t be complicated at all, but if you have just checked the tutorial it can be so. The map was made to give a better demonstration, so please check it.

When you have finished making your simple AI, try to add one or more of the following things to imrove it:

- Try to make it find the weakest enemy close.
- Try to make different AI players work together on killing a specific unit.
- When most battles becomes centered about the fountain, make heroes run away from it when they’re fleeing.
- Make the AI post text messages that varies depending on the situation (for example, an AI player can say “Die, sucker!” before killing you).

I hope this will help somebody!

Blade.dk
Attached Files
File Type: w3x AI Tutorial Arena.w3x (42.1 KB, 1070 views)
__________________
Spell Making Course: Part 1: Making a simple stomp spell.
I wonder if I'll ever finish part 2.
Blade.dk is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 01-23-2006, 09:12 PM   #2
Jacek
Banned
 
Join Date: Dec 2004
Posts: 1,095

Submissions (1)

Jacek is a jewel in the rough (164)Jacek is a jewel in the rough (164)

Send a message via MSN to Jacek
Default

I'm too lazy to read throught whole post, but...
Quote:
If the hero is about to die, order him/her/it to move to the fountain at the map center.
What if your hero has 15 hp, his hero has 100 hp, you are one-shot kill, but he runs to fountain?
Jacek is offline   Reply With Quote
Old 01-23-2006, 10:17 PM   #3
Taur
#8 in posting (nolifeftw)
 
Join Date: Jul 2005
Posts: 4,027

Taur is a jewel in the rough (215)Taur is a jewel in the rough (215)Taur is a jewel in the rough (215)Taur is a jewel in the rough (215)

Default

Jacek that is very impractical, sure blade could fix this but there are so many other scenarios, you can't just pick something out of the air and use it to critcize a good AI system, nor can you comment on something before you read it
Taur is offline   Reply With Quote
Old 01-23-2006, 10:21 PM   #4
Blade.dk
.
 
Blade.dk's Avatar


Respected User
 
Join Date: May 2005
Posts: 1,990

Submissions (15)

Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)

Approved Map: Azeroth's Arcane ArenaSpell session 01 winner

Send a message via MSN to Blade.dk
Default

Quote:
Originally Posted by Blade.dk
The AI you’ll learn how to make here will not be perfect. The one we will create here will attack other heroes, pick up items, learn and use spells, but it won’t be as effective as a human player.

Jacek, better read the whole thread before replying next time, that would be nice.
__________________
Spell Making Course: Part 1: Making a simple stomp spell.
I wonder if I'll ever finish part 2.
Blade.dk is offline   Reply With Quote
Old 01-27-2006, 04:03 PM   #5
Jacek
Banned
 
Join Date: Dec 2004
Posts: 1,095

Submissions (1)

Jacek is a jewel in the rough (164)Jacek is a jewel in the rough (164)

Send a message via MSN to Jacek
Default

Sorry if you received it like that, but I wasn't criticising that. I was just noting important thing.
Jacek is offline   Reply With Quote
Old 01-27-2006, 04:16 PM   #6
Blade.dk
.
 
Blade.dk's Avatar


Respected User
 
Join Date: May 2005
Posts: 1,990

Submissions (15)

Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)Blade.dk is a glorious beacon of light (418)

Approved Map: Azeroth's Arcane ArenaSpell session 01 winner

Send a message via MSN to Blade.dk
Default

I disagree, I don't think it is important when the purpose is to make it simple, that would require some things that would reduce the simplicity. I was not offended, I just prefer people reading the whole thing before answering, that's all.
__________________
Spell Making Course: Part 1: Making a simple stomp spell.
I wonder if I'll ever finish part 2.
Blade.dk is offline   Reply With Quote
Old 01-29-2006, 10:11 PM   #7
Anitarf
Procrastination Incarnate


Development Director
 
Join Date: Feb 2004
Posts: 8,190

Submissions (19)

Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)

2008 Spell olympics - Fire - SilverApproved Map: Old School Alliance TacticsHero Contest #2 - 3rd PlaceSpell making session 2 winner

Default

I think Jacek made a good point. I know this is the most basic arena AI possible, and you encourage players to improve upon it... but it would take an enormous ammount of improving to get this thing even remotely close to being able to match human players. Making the heroes fight is easy; heck, the heroes cast the abilities for you, unless you're an unlucky channel fan. Making them act with a strategic purpose is something else entirely.

I know, I'm a perfectionist. But I just don't see the point of making an AI if it can't actually replace a human player.
__________________
Anitarf is offline   Reply With Quote
Old 03-14-2006, 10:56 PM   #8
aquilla
User
 
aquilla's Avatar
 
Join Date: Mar 2003
Posts: 217

Submissions (1)

aquilla will become famous soon enough (71)aquilla will become famous soon enough (71)aquilla will become famous soon enough (71)

Send a message via MSN to aquilla
Default

Quote:
Originally Posted by Anitarf
I think Jacek made a good point. I know this is the most basic arena AI possible, and you encourage players to improve upon it... but it would take an enormous ammount of improving to get this thing even remotely close to being able to match human players. Making the heroes fight is easy; heck, the heroes cast the abilities for you, unless you're an unlucky channel fan. Making them act with a strategic purpose is something else entirely.

I know, I'm a perfectionist. But I just don't see the point of making an AI if it can't actually replace a human player.
As Taur said there are endless amounts of scenarios... Paladin healing a unit which is low on hp but unfocused while there is a unit with slightly higher hp which is being focused or maybe using it offensively. Chasing, say, a Mountain King who is low on hp just to get a stormbolt in yer head.

I don't really see the point in spending loads of time on an AI system when you can just play vs people. A simple one might be enough to let the game continue if someone leaves though Nice to see some still have the effort to write tutorials :)
aquilla is offline   Reply With Quote
Old 06-21-2006, 06:14 PM   #9
emjlr3
Rehabbing
 
emjlr3's Avatar
 
Join Date: Jun 2005
Posts: 1,386

Submissions (14)

emjlr3 is a jewel in the rough (151)emjlr3 is a jewel in the rough (151)

Mapping Contest First Place

Send a message via AIM to emjlr3 Send a message via MSN to emjlr3
Default

cool, this would have been helpful before I wrote my AI, but it is just exactly how I did mine, nice job with this

the only half comprehensive hero AI there is
__________________

Last edited by emjlr3 : 06-21-2006 at 06:14 PM.
emjlr3 is offline   Reply With Quote
Old 10-30-2006, 07:55 PM   #10
RikonVan
User
 
Join Date: Oct 2006
Posts: 1

RikonVan has little to show at this moment (0)

Default

Thank you veryverymuch!!!

Thx for your KI introduction. I read it and i was fascinated. My only plroblem was: I have much problems with JASS. I read much there but i didn't undersand anything. ...what can I do? Can you show me your KI scripts in the classic way not in jass or is it only possible in jass?
thx
Err how long takes it to learn JASS? How long takes it to understand what issuepointer(...) means?????

Last edited by RikonVan : 10-30-2006 at 08:00 PM.
RikonVan is offline   Reply With Quote
Old 02-07-2007, 12:49 PM   #11
kixer
User
 
kixer's Avatar
 
Join Date: Jan 2007
Posts: 4

kixer has little to show at this moment (0)

Default

Thanks for the nice simple tut...
Iv always wanted to get into ai...
but i need a good tut... Shot
__________________

This is what i have every morning

Last edited by kixer : 02-07-2007 at 12:56 PM.
kixer is offline   Reply With Quote
Old 04-05-2007, 06:30 PM   #12
vesuvan doppleganger
User
 
vesuvan doppleganger's Avatar
 
Join Date: Dec 2006
Posts: 131

vesuvan doppleganger is on a distinguished road (17)

Default

I think many of you are missing the possibilities here. Imagine using a system like this, along with the "ward classification trick" to create all kinds of games. Imagine a sort of 12 person FFA game where every player has their own party of bots. Oh the beautiful mayhem this would be in an arena. It would be like the ultimate showdown.

A tutorial or system shouldn't be taken for face value IMO. If you want it to do more, be creative, and build off the ideas.

Excellent tutorial blade. Its what got me started on making AIs for many types of maps, including AOSs, defenses, arenas, and more.
vesuvan doppleganger is offline   Reply With Quote
Old 12-09-2007, 07:20 AM   #13
bl00fire
User
 
Join Date: Nov 2007
Posts: 1

bl00fire has little to show at this moment (0)

Default

Great tutorial. Short and sweet, but fills a gap that other tutorials don't cover.

The presence of an "AI Editor" in WorldEdit makes the whole AI thing even more confusing. You might want explain how this triggered approach to AI has nothing to do with those melee .ai scripts.
bl00fire is offline   Reply With Quote
Old 10-17-2008, 03:29 PM   #14
waaaks
User
 
waaaks's Avatar
 
Join Date: Apr 2007
Posts: 356

waaaks is on a distinguished road (12)

Default

a bit old tutorial compared to modern vjass, can anyone revive this?
__________________
waaaks is offline   Reply With Quote
Old 10-17-2008, 08:33 PM   #15
Pyrogasm
Lackadaisically Absent.
 
Pyrogasm's Avatar


Respected User
 
Join Date: Sep 2006
Posts: 4,523

Submissions (9)

Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)

Hero Contest - Fourth place

Send a message via ICQ to Pyrogasm Send a message via AIM to Pyrogasm Send a message via MSN to Pyrogasm Send a message via Yahoo to Pyrogasm
Default

Uhhh... possibly. It's not really that hard to convert it.
__________________
Quote:
Originally posted by Rising_Dusk
Your spells are mostly ignored because they are not very cool so we aren't very excited to review/approve them, but you are incredibly persistent and won't give us an excuse to graveyard it. That is generally what results in a resource being ignored for a long time.

The Spell Request Thread Done for, unless someone else wants to revive it...
It lasted a damn long time.

Please; Ask for Help Appropriately














Quote:
Originally posted by Kyrbi0
Huh. Almost makes me wish I had a girlfriend, to take advantage of today (wait, no, that's not what I meant... I mean, take advantage of the fact that it is international women's day... gah, never mind).
Quote:
Originally posted by Pyrogasm
Rome may not have been built in a day, but the Romans sure as hell didn't say "look at this great city we built guys!" when they had nothing more than a bit of stone and some cottages.
Pyrogasm is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 09:19 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services