HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Some questions about melee A.I and the War3x Editor...

08-27-2003, 12:15 AM#1
Zycat
Firstly, the War3X editor won't load on my computer. The Windows always says that my display driver is corrupted after loading War3X editor so I need another way to "embed" my A.I into the maps.

And second, how to hire mercenaries and most importantly, merc heroes?
08-27-2003, 07:40 AM#2
Zalamander
You can try run the editor with OpenGL insted by running it from a shortcut with the "-opengl" commandline.
08-27-2003, 08:56 AM#3
AIAndy
Neutral Heroes cannot be easily bought with the AI.
AMAI uses direct orders to buy them. AMAI version 1.6 which will be released soon will contain an even better buy function.
Same problem with mercenaries and it is harder because you do not know which mercenaries are available unless you write an AI for a specific map.
08-28-2003, 04:02 AM#4
dataangel
Get new video drivers if you haven't already.
08-30-2003, 08:41 AM#5
Zycat
I tried all versions of nVidia video drivers, nothing works :nono:

Yeah, even with the -opengl option on it still says my video driver is corrupted, and switches to 640x480x16 mode :nono:

Next q : How many threads max we can start with StartThread?
08-30-2003, 10:32 AM#6
AIAndy
6 threads can be started inclusive all the threads started by common.ai .
08-31-2003, 12:57 PM#7
Zycat
That means only one thread left :bgrun:

I need a method for communication between A.I allies and A.I with human allies. Is there shared variables or string parsing?
08-31-2003, 02:09 PM#8
AIAndy
No shared variables and reading chat entries does not work from AI (because triggers do not work, they need callbacks). If you want to communicate with human allies you will have to do it like AMAI in the map script or Blizzard.j .
Communication between AI allies works with AI commands and Alliance target.
If you don't have enough threads you could use the timed job system used in AMAI 1.6 . It allows to time jobs executing them at the time specified. It uses a priority heap and is quite efficient.
09-01-2003, 12:01 AM#9
Zycat
Ok, can you explain to me about AI commands for AI-to-AI communications? What functions/methods should I use?

Does modifying blizzard.j safe for multiplayer use?
09-01-2003, 02:04 AM#10
AIAndy
Blizzard.j can be included in a map and it works fine (although it is not that small so if you only want it for a specific map rather put it in the map script).

native CommandAI takes player num, integer command, integer data returns nothing

With this native you can send a command consisting of a command number and an integer as data to an AI (you can interpret these numbers however you like). Origin does not matter so it can be used from both AI and trigger. The command is then put on a stack (there is one for each AI).

native CommandsWaiting takes nothing returns integer
native GetLastCommand takes nothing returns integer
native GetLastData takes nothing returns integer
native PopLastCommand takes nothing returns nothing

With these natives you can then read the stack in the AI (mind that a stack means last in first out, which is relevant when you send multiple commands at the same time).
CommandsWaiting returns the number of commands on the stack.
GetLastCommand retrieves the command number of the command on the top of the stack.
GetLastData returns the data number.
PopLastCommand removes the topmost element of the stack.
09-10-2003, 11:18 AM#11
Zycat
Ok thanks, that worked well :ggani:

Now, how to send resources to a player using normal resource trading means (and this means the end game result shows how much resource is traded. If I just use a simple resource add/remove from players it won't show anything...)
09-10-2003, 02:19 PM#12
AIAndy
I don't think there is a way to do that. (I'd have used it in AMAI, if I knew of any way) Currently I think you have to use the resource add / remove.
09-14-2003, 01:00 AM#13
Zycat
Quote:
Originally posted by AIAndy
Same problem with mercenaries and it is harder because you do not know which mercenaries are available unless you write an AI for a specific map.


You know, you can actually do this :

Code:
    //--------------------------------------------------------------------
    // Neutral Hireable Mercenaries
    //--------------------------------------------------------------------

    //--- Ashenvale
    constant integer SATYR_SHADOWDANCER = 'nsts'
    constant integer FURBOLG_SHAMAN     = 'nfrs'
    constant integer THUNDER_LIZARD     = 'nthl'

    //--- Barrens
    constant integer CENTAUR_OUTRUNNER  = 'ncen'
    constant integer HARPY_ROGUE        = 'nhrr'
    constant integer RAZORMANE_MEDICINE_MAN = 'nrzm'
    constant integer HARPY_WINDWITCH    = 'nhrw'

    //--- Black Citadel and Outland
    constant integer FEL_BEAST          = 'npfl'
    constant integer DRAENEI_DISCIPLE   = 'ndrm'
    constant integer VOIDWALKER         = 'nvdw'
    constant integer DRAENEI_DARKSLAYER = 'ndrd'

    //--- Cityscape, Dalaran, and Dalaran Ruins
    constant integer ROGUE              = 'nrog'
    constant integer ASSASSIN           = 'nass'
    constant integer KOBOLD_GEOMANCER   = 'nkog'
    constant integer FOREST_TROLL_HIGH_PRIEST = 'nfsh'

    //--- Dungeon and Underground
    constant integer BURNING_ARCHER     = 'nskf'
//    constant integer KOBOLD_GEOMANCER   = 'nkog'
    constant integer WILDKIN            = 'nowb'              // owlbear

    //--- Felwood
    constant integer MURLOC_FLESHEATER  = 'nmfs'
    constant integer SLUDGE_FLINGER     = 'nslf'
    constant integer SATYR_SOULSTEALER  = 'nstl'

    //--- Icecrown Glacier
    constant integer BARBED_ARACHNATHID = 'nanm'
    constant integer BLUE_DRAGONSPAWN_MEDDLER = 'nbdm'
    constant integer MAGNATAUR_WARRIOR  = 'nmgw'
    constant integer POLAR_FURBOLG_SHAMAN = 'nfps'

    //--- Lordaeron Fall
    constant integer GNOLL_BRUTE        = 'ngnb'
    constant integer GNOLL_WARDEN       = 'ngnw'
    constant integer OGRE_MAGI          = 'nomg'
    constant integer MUD_GOLEM          = 'ngrk'

    //--- Lordaeron Summer
    constant integer FOREST_TROLL_BERSERKER = 'nftb'
    constant integer FOREST_TROLL_SHADOW_PRIEST = 'nfsp'
    constant integer OGRE_MAULER          = 'nogm'
//    constant integer MUD_GOLEM          = 'ngrk'    

    //--- Lordaeron Winter
    constant integer GNOLL_OVERSEER     = 'ngnv'
    constant integer ICE_TROLL_BERSERKER = 'nits'
    constant integer ICE_TROLL_TRAPPER  = 'nitt'
//    constant integer MUD_GOLEM          = 'ngrk'    

    //--- Northrend
    constant integer NERUBIAN_WARRIOR    = 'nnwa'
//    constant integer ICE_TROLL_BERSERKER = 'nits'
    constant integer FROST_REVENANT      = 'nrvs'
    constant integer NERUBIAN_WEBSPINNER = 'nnwl'    

    //--- Sunken Ruins
    constant integer MURGUL_SNARECASTER  = 'nmsn'
    constant integer MAKRURA_SNAPPER     = 'nlsn'
    constant integer MAKRURA_DEEPSEER    = 'nlds'
    constant integer GIANT_SEA_TURTLE    = 'ntrt'

    //--- Village
    constant integer KOBOLD             = 'nkob'
    constant integer MURLOC_HUNTSMAN    = 'nmrr'
//    constant integer ASSASSIN           = 'nass'
//    constant integer KOBOLD_GEOMANCER   = 'nkog'

    //--------------------------------------------------------------------
    // Neutral Hireable Dragons
    //--------------------------------------------------------------------

    //--- Black
    constant integer BLACK_DRAGON_1     = 'nbdr'
    constant integer BLACK_DRAGON_2     = 'nbdk'
    constant integer BLACK_DRAGON_3     = 'nbwm'

    //--- Blue
    constant integer BLUE_DRAGON_1     = 'nadw'
    constant integer BLUE_DRAGON_2     = 'nadk'
    constant integer BLUE_DRAGON_3     = 'nadr'

    //--- Bronze
    constant integer BRONZE_DRAGON_1     = 'nbzw'
    constant integer BRONZE_DRAGON_2     = 'nbzk'
    constant integer BRONZE_DRAGON_3     = 'nbzd'

    //--- Green
    constant integer GREEN_DRAGON_1     = 'ngrw'
    constant integer GREEN_DRAGON_2     = 'ngdk'
    constant integer GREEN_DRAGON_3     = 'ngrd'

    //--- Nether
    constant integer NETHER_DRAGON_1     = 'nnht'
    constant integer NETHER_DRAGON_2     = 'nndk'
    constant integer NETHER_DRAGON_3     = 'nndr'

    //--- Red
    constant integer RED_DRAGON_1     = 'nrdk'
    constant integer RED_DRAGON_2     = 'nrdr'
    constant integer RED_DRAGON_3     = 'nrwm'

    //--------------------------------------------------------------------
    constant integer M1                 =    60
    constant integer M2                 =  2*60
    constant integer M3                 =  3*60
    constant integer M4                 =  4*60
    constant integer M5                 =  5*60
    constant integer M6                 =  6*60
    constant integer M7                 =  7*60
    constant integer M8                 =  8*60
    constant integer M9                 =  9*60
    constant integer M10                = 10*60
    constant integer M11                = 11*60
    constant integer M12                = 12*60
    constant integer M13                = 13*60
    constant integer M14                = 14*60
    constant integer M15                = 15*60

    constant integer EASY               = 1
    constant integer NORMAL             = 2
    constant integer HARD               = 3
    constant integer INSANE             = 4 // not used

    constant integer MELEE_NEWBIE       = 1
    constant integer MELEE_NORMAL       = 2
    constant integer MELEE_INSANE       = 3

    constant integer ATTACK_CAPTAIN     = 1
    constant integer DEFENSE_CAPTAIN    = 2
    constant integer BOTH_CAPTAINS      = 3

    constant integer BUILD_UNIT         = 1
    constant integer BUILD_UPGRADE      = 2
    constant integer BUILD_EXPAND       = 3

    constant integer UPKEEP_TIER1       = 50
    constant integer UPKEEP_TIER2       = 80

Code:
//==========================================================================
//	CheckDragon
//==========================================================================
function CheckDragon takes nothing returns nothing
  local group g = CreateGroup()
  local unit u = null
  local string s = "dragonroost"
  local string add = "black"
  local integer i = 0
  local boolean found = false

  loop
     exitwhen i >= 6 or found
     set i = i + 1

     if i == 1 then
        set add = "black"
     elseif i == 2 then
        set add = "blue"
     elseif i == 3 then
        set add = "bronze"
     elseif i == 4 then
        set add = "green"
     elseif i == 5 then
        set add = "outland"
     elseif i == 6 then
        set add = "red"
     endif

     call GroupEnumUnitsOfType(g, add+s , null)
     if FirstOfGroup(g) != null then
         set dragon_available = true
         set nearest_dragon_roost = GetNearestOfGroup(g, GetPlayerStartLocationLoc(Player(GetAiPlayer())))
         set dragon_roost_guarded = GetLocationCreepStrength(GetUnitX(nearest_observatory), GetUnitY(nearest_observatory), 500) > 0
         set found = true
         if i == 1 then
            set dragon_types[1] = BLACK_DRAGON_1
            set dragon_types[2] = BLACK_DRAGON_2
            set dragon_types[3] = BLACK_DRAGON_3
         elseif i == 2 then
            set dragon_types[1] = BLUE_DRAGON_1
            set dragon_types[2] = BLUE_DRAGON_2
            set dragon_types[3] = BLUE_DRAGON_3
         elseif i == 3 then
            set dragon_types[1] = BRONZE_DRAGON_1
            set dragon_types[2] = BRONZE_DRAGON_2
            set dragon_types[3] = BRONZE_DRAGON_3
         elseif i == 4 then
            set dragon_types[1] = GREEN_DRAGON_1
            set dragon_types[2] = GREEN_DRAGON_2
            set dragon_types[3] = GREEN_DRAGON_3
         elseif i == 5 then
            set dragon_types[1] = NETHER_DRAGON_1
            set dragon_types[2] = NETHER_DRAGON_2
            set dragon_types[3] = NETHER_DRAGON_3
         elseif i == 6 then
            set dragon_types[1] = RED_DRAGON_1
            set dragon_types[2] = RED_DRAGON_2
            set dragon_types[3] = RED_DRAGON_3
         endif
     endif
  endloop
endfunction

//==========================================================================
//	CheckMercenary
//==========================================================================
function CheckMercenary takes nothing returns nothing
  local group g = CreateGroup()
  local unit u = null
  local string s = "mercenarycamp"
  local string add = "a"
  local integer i = 0
  local boolean found = false

  loop
     exitwhen i >= 16 or found
     set i = i + 1

     if i == 1 then
        set add = "a"
     elseif i == 2 then
        set add = "b"
     elseif i == 3 then
        set add = "k"
     elseif i == 4 then
        set add = "y"
     elseif i == 5 then
        set add = "x"
     elseif i == 6 then
        set add = "d"
     elseif i == 7 then
        set add = "c"
     elseif i == 8 then
        set add = "i"
     elseif i == 9 then
        set add = "f"
     elseif i == 10 then
        set add = "l"
     elseif i == 11 then
        set add = "w"
     elseif i == 12 then
        set add = "n"
     elseif i == 13 then
        set add = "o"
     elseif i == 14 then
        set add = "z"
     elseif i == 15 then
        set add = "g"
     elseif i == 16 then
        set add = "v"
     endif

     call GroupEnumUnitsOfType(g, s+add , null)
     if FirstOfGroup(g) != null then
         set mercenary_available = true
         set nearest_merc_camp = GetNearestOfGroup(g, GetPlayerStartLocationLoc(Player(GetAiPlayer())))
         set merc_camp_guarded = GetLocationCreepStrength(GetUnitX(nearest_observatory), GetUnitY(nearest_observatory), 500) > 0
         set found = true
         if i == 1 then
            set merc_unit_types[1] = SATYR_SHADOWDANCER
            set merc_unit_types[2] = FURBOLG_SHAMAN
            set merc_unit_types[3] = THUNDER_LIZARD
            set merc_types = 3
         elseif i == 2 then
            set merc_unit_types[1] = CENTAUR_OUTRUNNER
            set merc_unit_types[2] = HARPY_ROGUE
            set merc_unit_types[3] = RAZORMANE_MEDICINE_MAN
            set merc_unit_types[4] = HARPY_WINDWITCH
            set merc_types = 4
         elseif i == 3 or i == 13 then
            set merc_unit_types[1] = FEL_BEAST
            set merc_unit_types[2] = DRAENEI_DISCIPLE
            set merc_unit_types[3] = VOIDWALKER
            set merc_unit_types[4] = DRAENEI_DARKSLAYER
            set merc_types = 4
         elseif i == 4 or i == 5 then
            set merc_unit_types[1] = ROGUE
            set merc_unit_types[2] = ASSASSIN
            set merc_unit_types[3] = KOBOLD_GEOMANCER
            set merc_unit_types[4] = FOREST_TROLL_HIGH_PRIEST
            set merc_types = 4
         elseif i == 6 or i == 15 then
            set merc_unit_types[1] = BURNING_ARCHER
            set merc_unit_types[2] = KOBOLD_GEOMANCER
            set merc_unit_types[3] = WILDKIN
            set merc_types = 3
         elseif i == 7 then
            set merc_unit_types[1] = MURLOC_FLESHEATER
            set merc_unit_types[2] = SLUDGE_FLINGER
            set merc_unit_types[3] = SATYR_SOULSTEALER
            set merc_types = 3
         elseif i == 8 then
            set merc_unit_types[1] = BARBED_ARACHNATHID
            set merc_unit_types[2] = BLUE_DRAGONSPAWN_MEDDLER
            set merc_unit_types[3] = MAGNATAUR_WARRIOR
            set merc_unit_types[4] = POLAR_FURBOLG_SHAMAN
            set merc_types = 4
         elseif i == 9 then
            set merc_unit_types[1] = GNOLL_BRUTE
            set merc_unit_types[2] = GNOLL_WARDEN
            set merc_unit_types[3] = OGRE_MAGI
            set merc_unit_types[4] = MUD_GOLEM
            set merc_types = 4
         elseif i == 10 then
            set merc_unit_types[1] = FOREST_TROLL_BERSERKER
            set merc_unit_types[2] = FOREST_TROLL_SHADOW_PRIEST
            set merc_unit_types[3] = OGRE_MAULER
            set merc_unit_types[4] = MUD_GOLEM
            set merc_types = 4
         elseif i == 11 then
            set merc_unit_types[1] = GNOLL_OVERSEER
            set merc_unit_types[2] = ICE_TROLL_BERSERKER
            set merc_unit_types[3] = ICE_TROLL_TRAPPER
            set merc_unit_types[4] = MUD_GOLEM
            set merc_types = 4
         elseif i == 12 then
            set merc_unit_types[1] = NERUBIAN_WARRIOR
            set merc_unit_types[2] = ICE_TROLL_BERSERKER
            set merc_unit_types[3] = FROST_REVENANT
            set merc_unit_types[4] = NERUBIAN_WEBSPINNER
            set merc_types = 4
         elseif i == 14 then
            set merc_unit_types[1] = MURGUL_SNARECASTER
            set merc_unit_types[2] = MAKRURA_SNAPPER
            set merc_unit_types[3] = MAKRURA_DEEPSEER
            set merc_unit_types[4] = GIANT_SEA_TURTLE
            set merc_types = 4
         elseif i == 16 then
            set merc_unit_types[1] = KOBOLD
            set merc_unit_types[2] = MURLOC_HUNTSMAN
            set merc_unit_types[3] = ASSASSIN
            set merc_unit_types[4] = KOBOLD_GEOMANCER
            set merc_types = 4
         endif
     endif
  endloop
  set random_merc_type = GetRandomInt(1,merc_types)
endfunction

And it works fine!:ggani:
09-14-2003, 10:39 AM#14
AIAndy
:D
Wow, nice code. I never knew that mercenary camps were actually different buildings.
There is a small bug in the guarded check you do. You need to replace nearest_observatory there with the nearest_dragon_roost respective nearest_merc_camp .
Now we just have to come up with some good way to determine when to buy them (best dividing them into different categories) and putting them in the unit information arrays with a new id and their available_time so they can be used with SetBuildUnit. Then they can be used in AMAI :gsmile: .

Do you have an ICQ# ?
09-14-2003, 01:12 PM#15
Zycat
0_o thx, I never knew that camp guarded bug lol :ggani:

Anyway, for dragons, you better not buy them unless they're aren't guarded. Lv. 10 Dragons don't sleep ya know

I uses 440 seconds game time as the minimal buy time, since if you take a look of their first available-to-hire times you'll notice that almost all of them has 440.

For dragons, it depends only on their "size" (whelp, drake, mature dragons). Colour doesn't matter.

Another problem I encountered is that sometimes different A.I players tries to get the same merc...

---
If I'm not mistaken there is a formula of r creep buy respawn time... I heard of it somewhere... and I think it's based on the creeps' level.

Edited because: Merc regeneration times are typically level/food cost of Merc * 50 sec. + 10 sec. from http://www.battle.net/war3/neutral/b...#mercenarycamp :D

My ICQ# is 72579615... but I don't use ICQ often.
If you can use MSN instead... my id is [email protected]
.