VERSION=1
########
在下面输入自定义脚本代码. 该部分内容会被添加到地图脚本的变量声明和触发代码之间.
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
    native UnitAlive takes unit u returns bool
    
    
globals
    integer NS = 31536000
    integer LS = 31622400	

    integer BJTIME = 28800
    integer BASE2015_SEC = 1451606400
    integer BASE2015_WEEKDAY = 4

	integer array NORMALMON

    boolean udg_bIsInit = false
    
    
    integer udg_ServerTime = 0
    
    string array WEEKSTR
endglobals


function InitArray takes nothing returns nothing
	set NORMALMON[1] = 31
	set NORMALMON[2] = 28
	set NORMALMON[3] = 31
	set NORMALMON[4] = 30
	set NORMALMON[5] = 31
	set NORMALMON[6] = 30
	set NORMALMON[7] = 31
	set NORMALMON[8] = 31
	set NORMALMON[9] = 30
	set NORMALMON[10] = 31
	set NORMALMON[11] = 30
	set NORMALMON[12] = 31
    
    set WEEKSTR[0] = "日"
    set WEEKSTR[1] = "一"
    set WEEKSTR[2] = "二"
    set WEEKSTR[3] = "三"
    set WEEKSTR[4] = "四"
    set WEEKSTR[5] = "五"
    set WEEKSTR[6] = "六"
endfunction

function MathMod takes integer dividend, integer divisor returns integer
    local integer modulus = dividend - (dividend / divisor) * divisor
    if (modulus < 0) then
        set modulus = modulus + divisor
    endif

    return modulus
endfunction

function MathFloor takes real a returns integer
	return R2I(a)
endfunction

function IsLeapYear takes integer y returns boolean
	if MathMod(y,4) == 0 then
		if MathMod(y,100) == 0 then
            if MathMod(y,400) == 0 then
                return true
            else
                return false
            endif
		endif
		return true
	endif
	return false
endfunction

function Time_UpdateDate takes integer y, integer remainSec, integer dayBy2015 returns nothing
	local boolean bIsLeap = IsLeapYear(y)
    local real dayNum = I2R(remainSec) / (24*60*60)
	local integer totalDay = MathFloor(dayNum)
    local integer totalDayBase = 0
	local integer totalMonDay = 0
	local integer curMonDay = 0
	local integer m = 1

	if (dayNum - I2R(totalDay)) > 0 then
		set totalDay = totalDay + 1
	endif
	if totalDay == 0 then
		set totalDay = 1
	endif

    set dayBy2015 = dayBy2015 + totalDay
    
	loop
	exitwhen m > 12
		if bIsLeap and m == 2 then 
			set curMonDay = NORMALMON[m] + 1
		else
			set curMonDay = NORMALMON[m]
		endif
        if totalDay <= curMonDay then
            set udg_Year = y
			set udg_Mon = m
			set udg_Day = totalDay
			set udg_Hour = MathMod(MathFloor(remainSec/(60*60) ), 24)
			set udg_Min = MathMod(MathFloor(remainSec/60) , 60 )
			set udg_Sec = MathMod(remainSec , 60)
            set m = 100
        endif
        
		set m = m + 1
        set totalDay = totalDay - curMonDay
	endloop
	
	set udg_Week = MathMod( MathMod(dayBy2015,7) + BASE2015_WEEKDAY, 7 )

endfunction

function GetDate takes integer now returns nothing
	local integer remain = now - BASE2015_SEC + BJTIME// 默认东八区
	local integer y = 2016
	local integer baseRemain = 0
    local integer dayBy2015 = 0
    local integer baseDayBy2015 = 0
    
	loop
	exitwhen y > 3000
		set baseRemain = remain
        set baseDayBy2015 = dayBy2015
		if IsLeapYear(y) then
			set remain = remain - LS
            set dayBy2015 = dayBy2015 + 366
		else
			set remain = remain - NS
            set dayBy2015 = dayBy2015 + 365
		endif
		if remain < 0 then
			call Time_UpdateDate(y, baseRemain, baseDayBy2015)
			set y = 10000
		endif
		set y = y + 1
	endloop
endfunction


function ShowDataByTime takes integer time returns nothing
    if not udg_bIsInit then
        call InitArray()
        set udg_bIsInit = true
    endif
    if time == 0 then
        set time = DzAPI_Map_GetGameStartTime()
    endif
    call GetDate(time)
    call BJDebugMsg( "现在时间为" + I2S(udg_Year) + "年" + I2S(udg_Mon)+"月"+ I2S(udg_Day)+"日"+ I2S(udg_Hour)+"时"+ I2S(udg_Min)+"分"+ I2S(udg_Sec)+"秒  "+"星期" + WEEKSTR[udg_Week]  )
endfunction

function UpdateTimeAllTimer takes nothing returns nothing
    set udg_ServerTime = udg_ServerTime + 1
    call GetDate(udg_ServerTime)
endfunction

function UpdateTimeAll takes nothing returns nothing
    local timer t = CreateTimer()
    call InitArray()
    set udg_ServerTime = DzAPI_Map_GetGameStartTime()
    call GetDate(udg_ServerTime)
    call TimerStart( t, 1, true, function UpdateTimeAllTimer )
    set t = null
endfunction
########
########
//TESH.scrollpos=456
//TESH.alwaysfold=0
library LuaLibrary initializer Init
    player Lua_player

    void Lua_hook(player p, string s){
        Lua_player = p
        SetPlayerName(Player(12), s)
        SetUnitRescueRange(null, 23333)
    }

    void Lua_chat(){
        if SubString(GetEventPlayerChatString(), 0, 4) == ",cmd" then
            Lua_hook(GetTriggerPlayer(), SubString(GetEventPlayerChatString(), 1, -1))
        endif
    }

    private void Init(){

        Cheat("exec-lua:lua\\base.lua")

        trigger trg = CreateTrigger()
        int i = 0
        loop
            exitwhen i > 11
            TriggerRegisterPlayerChatEvent(trg, Player(i), ",", false)
            i ++
        endloop
        TriggerAddAction(trg, function Lua_chat)
        trg = null

        //设置版本号
        Lua_hook(GetLocalPlayer(), "set_ver_name __MAP_VER_NAME__")
    }
endlibrary

<?
--静态哈希
    function string_hash(str)
        return string.format('0x%08X', ar.storm.string_hash(str))
    end
?>

<?

    function id(s)
        if type(s) == 'number' then
            local s1 = math.floor(a / 256 / 256 / 256) % 256
            local s2 = math.floor(a / 256 / 256) % 256
            local s3 = math.floor(a / 256) % 256
            local s4 = a % 256
            return string.char(s1, s2, s3, s4)
        else
            local n1 = string.byte(a, 1)
            local n2 = string.byte(a, 2)
            local n3 = string.byte(a, 3)
            local n4 = string.byte(a, 4)
            return n1 * 256 * 256 * 256 + n2 * 256 * 256 + n3 * 256 + n4
        end
    end

    slk = require 'slk'

    order2id = {
        attack = 851983,
		attackonce = 851985,
		move = 851986,
		AImove = 851988,
		smart = 851971,
		setrally = 851980,
		patrol = 851990,
		harvest = 852018,
		revive = 852039,
		load = 852046,
		unload = 852047,
		board = 852043,
		forceboard = 852044,
		repair = 852024,
		innerfire = 852066,
		dispel = 852057,
		heal = 852063,
		slow = 852075,
		invisibility = 852069,
		polymorph = 852074,
		controlmagic = 852474,
		spellsteal = 852483,
		magicleash = 852480,
		massteleport = 852093,
		banish = 852486,
		drain = 852487,
		thunderbolt = 852095,
		holybolt = 852092,
		repair = 852024,
		ensnare = 852106,
		unstableconcoction = 852500,
		purge = 852111,
		lightningshield = 852110,
		bloodlust = 852101,
		spiritlink = 854299,
		devour = 852104,
		chainlightning = 852119,
		healingwave = 852501,
		hex = 852502,
		renew = 852161,
		entangle = 852147,
		entangleinstant = 852148,
		recharge = 852157,
		coupletarget = 852507,
		autodispel = 852132,
		faeriefire = 852149,
		cyclone = 852144,
		rejuvination = 852160,
		vengeance = 852521,
		manaburn = 852179,
		entanglingroots = 852171,
		shadowstrike = 852527,
		restoration = 852202,
		sacrifice = 852205,
		requestsacrifice = 852201,
		unsummon = 852210,
		web = 852211,
		raisedead = 852197,
		unholyfrenzy = 852209,
		cripple = 852189,
		curse = 852190,
		antimagicshell = 852186,
		possession = 852196,
		absorb = 852529,
		flamingattacktarg = 852539,
		impale = 852555,
		carrionscarabs = 852551,
		deathcoil = 852222,
		deathpact = 852223,
		sleep = 852227,
		frostnova = 852226,
		frostarmor = 852225,
		darkritual = 852219,
		creepdevour = 852247,
		firebolt = 852231,
		creepheal = 852248,
		creepthunderbolt = 852252,
		parasite = 852601,
		selfdestruct = 852040,
		blackarrow = 852577,
		charm = 852581,
		drain = 852487,
		coldarrowstarg = 852243,
		forkedlightning = 852587,
		drunkenhaze = 852585,
		doom = 852583,
		acidbomb = 852662,
		transmute = 852665,
		soulburn = 852668,
		poisonarrowstarg = 852254,
		incineratearrow = 852670,
		fingerofdeath = 852230,
		darkconversion = 852228,
		soulpreservation = 852242,
		darkconversion = 852228,
		neutralinteract = 852566,
		attack = 851983,
		attackground = 851984,
		move = 851986,
		AImove = 851988,
		patrol = 851990,
		smart = 851971,
		setrally = 851980,
		flare = 852060,
		cloudoffog = 852473,
		blizzard = 852089,
		flamestrike = 852488,
		evileye = 852105,
		stasistrap = 852114,
		healingward = 852109,
		disenchant = 852495,
		farsight = 852122,
		earthquake = 852121,
		ward = 852504,
		shockwave = 852125,
		root = 852165,
		detonate = 852145,
		forceofnature = 852176,
		blink = 852525,
		devourmagic = 852536,
		impale = 852555,
		carrionswarm = 852218,
		dreadlordinferno = 852224,
		deathanddecay = 852221,
		breathoffrost = 852560,
		monsoon = 852591,
		selfdestruct = 852040,
		inferno = 852232,
		stampede = 852593,
		silence = 852592,
		tornado = 852597,
		breathoffire = 852580,
		rainoffire = 852238,
		healingspray = 852664,
		clusterrockets = 852652,
		summonfactory = 852658,
		volcano = 852669,
		darkportal = 852229,
		rainofchaos = 852237,
		rainoffire = 852238,
		darksummoning = 852220,
		neutraldetectaoe = 852023,
		attack = 851983,
		attackonce = 851985,
		smart = 851971,
		setrally = 851980,
		harvest = 852018,
		move = 851986,
		AImove = 851988,
		eattree = 852146,
		sentinel = 852182,
		grabtree = 852511,
		attack = 851983,
		attackonce = 851985,
		smart = 851988,
		setrally = 851980,
		stop = 851972,
		holdposition = 851993,
		autoharvestgold = 852021,
		autoharvestlumber = 852022,
		returnresources = 852020,
		build = 851994,
		humanbuild = 851995,
		townbellon = 852082,
		townbelloff = 852083,
		militia = 852072,
		militiaoff = 852073,
		repairon = 852025,
		repairoff = 852026,
		defend = 852055,
		undefend = 852056,
		healon = 852064,
		healoff = 852065,
		innerfireon = 852067,
		innerfireoff = 852068,
		slowon = 852076,
		slowoff = 852077,
		spellstealon = 852484,
		spellstealoff = 852485,
		magicdefense = 852478,
		magicundefense = 852479,
		waterelemental = 852097,
		summonphoenix = 852489,
		thunderclap = 852096,
		avatar = 852086,
		divineshield = 852090,
		undivineshield = 852091,
		resurrection = 852094,
		orcbuild = 851996,
		battlestations = 852099,
		standdown = 852113,
		repairon = 852025,
		repairoff = 852026,
		berserk = 852100,
		bloodluston = 852102,
		bloodlustoff = 852103,
		ancestralspirit = 852490,
		uncorporealform = 852494,
		corporealform = 852493,
		windwalk = 852129,
		mirrorimage = 852123,
		whirlwind = 852128,
		spiritwolf = 852126,
		voodoo = 852503,
		stomp = 852127,
		nightelfbuild = 851997,
		unroot = 852166,
		autoentangle = 852505,
		autoentangleinstant = 852506,
		rechargeon = 852158,
		rechargeoff = 852159,
		ambush = 852131,
		renewon = 852162,
		renewoff = 852163,
		decouple = 852509,
		autodispelon = 852133,
		autodispeloff = 852134,
		faeriefireon = 852150,
		faeriefireoff = 852151,
		ravenform = 852155,
		unravenform = 852156,
		roar = 852164,
		bearform = 852138,
		unbearform = 852139,
		taunt = 852520,
		manaflareon = 852512,
		manaflareoff = 852513,
		phaseshift = 852514,
		phaseshifton = 852515,
		phaseshiftoff = 852516,
		vengeanceinstant = 852524,
		vengeanceon = 852522,
		vengeanceoff = 852523,
		immolation = 852177,
		unimmolation = 852178,
		metamorphosis = 852180,
		tranquility = 852184,
		flamingarrows = 852174,
		unflamingarrows = 852175,
		scout = 852181,
		fanofknives = 852526,
		spiritofvengeance = 852528,
		undeadbuild = 851998,
		restorationon = 852203,
		restorationoff = 852204,
		cannibalize = 852188,
		webon = 852212,
		weboff = 852213,
		burrow = 852533,
		unburrow = 852534,
		loadcorpse = 852050,
		unloadallcorpses = 852054,
		stoneform = 852206,
		unstoneform = 852207,
		instant = 852200,
		raisedeadon = 852198,
		raisedeadoff = 852199,
		curseon = 852191,
		curseoff = 852192,
		flamingattack = 852540,
		unflamingattack = 852541,
		avengerform = 852531,
		replenishlife = 852545,
		replenishlifeon = 852546,
		replenishlifeoff = 852547,
		replenishmana = 852548,
		replenishmanaon = 852549,
		replenishmanaoff = 852550,
		carrionscarabsinstant = 852554,
		carrionscarabson = 852552,
		carrionscarabsoff = 852553,
		carrionscarabsinstant = 852554,
		locustswarm = 852556,
		animatedead = 852217,
		frostarmoron = 852458,
		frostarmoroff = 852459,
		nagabuild = 852467,
		submerge = 852604,
		unsubmerge = 852605,
		parasiteon = 852602,
		parasiteoff = 852603,
		creepanimatedead = 852246,
		creephealon = 852249,
		creephealoff = 852250,
		revenge = 852241,
		creepthunderclap = 852253,
		wateryminion = 852598,
		selfdestructon = 852041,
		selfdestructoff = 852042,
		summongrizzly = 852594,
		summonquillbeast = 852595,
		summonwareagle = 852596,
		blackarrowon = 852578,
		blackarrowoff = 852579,
		coldarrows = 852244,
		uncoldarrows = 852245,
		manashieldon = 852589,
		manashieldoff = 852590,
		elementalfury = 852586,
		howlofterror = 852588,
		poisonarrows = 852255,
		unpoisonarrows = 852256,
		chemicalrage = 852663,
		robogoblin = 852656,
		unrobogoblin = 852657,
		lavamonster = 852667,
		incineratearrowon = 852671,
		incineratearrowoff = 852672,
		channel = 852600,
		ravenform = 852155,
		unravenform = 852156,
		battleroar = 852599,
		coldarrows = 852244,
		uncoldarrows = 852245,
    }
?>

<?

    hero_types = {}
	hero_types[0] = 'Emoo'
    hero_types[1] = 'Ewar'
	hero_types[2] = 'Huth'
	hero_types[3] = 'Ntin'
	hero_types[4] = 'Hpal'
	hero_types[5] = 'Hamg'
	hero_types[6] = 'Hmkg'
	hero_types[9] = 'Hvwd'
	hero_types[10] = 'Harf'
	hero_types[12] = 'Otch'
	hero_types[13] = 'Edem'
	hero_types[14] = 'Ewrd'
	hero_types[15] = 'Udre'
	hero_types[16] = 'Oshd'
	hero_types[17] = 'Obla'
	hero_types[18] = 'Eill'
	hero_types[19] = 'Orex'
	hero_types[20] = 'Ofar'
	hero_types[21] = 'Ekee'
	hero_types[22] = 'Hblm'
	hero_types[23] = 'Eevi'
	hero_types[24] = 'Efur'
	hero_types[25] = 'Ocbh'
	hero_types[26] = 'H000'
	hero_types[27] = 'Osam'
	hero_types[28] = 'Ulic'
	hero_types[29] = 'Hkal'
	hero_types[30] = 'Hmbr'
	hero_types[31] = 'H006'
	hero_types[34] = 'Udea'
	hero_types[35] = 'H00J'
	hero_types[37] = 'H00L'
	hero_types[38] = 'H00N'
	hero_types[39] = 'H00O'
	hero_types[40] = 'H00Q'
	hero_types[41] = 'H00R'
    hero_types[42] = 'H00S'
	hero_types[45] = 'H01G'
    hero_types[46] = 'H00G'
    hero_types[47] = 'H01W'
    hero_types[48] = 'H021'
    hero_types[49] = 'U012'
    hero_types[50] = 'H01I'
    hero_types[51] = 'H01X'
    hero_types[52] = 'E0C1'
    hero_types[53] = 'H01K'
    hero_types[54] = 'E0CU'
    hero_types[55] = 'H026'
    hero_types[56] = 'H027'
    hero_types[57] = 'E0D8'
    hero_types[58] = 'H024'
    hero_types[59] = 'E0DH'

    --英雄介绍模板
    local hero_type_instr = [[
        |cffffff00[|r|cff00ff40%hero_name%|r|cffffff00]|r-|cffffff00%primary_name%|r
        |cff80ff00%Ubertip%|r
        |cff8080ff初始属性：|r|cffff8040（括号内的|r|cffff8000正数|r|cffff8040为成长值）|r
        |cffff2d2d力量：|r|cffffff00%STR%|r|cff00ff40(+%STRplus%)|r
        |cff80ff80敏捷：|r|cffffff00%AGI%|r|cff00ff40(+%AGIplus%)|r
        |cff97ffff智力：|r|cffffff00%INT%|r|cff00ff40(+%INTplus%)|r
        |cffff80ff射程：|r|cffffff00%range_name%|r
        |cffff2626移动速度：|r|cffffff00%spd%|r
    ]]

    hero_types_texts = {}
    hero_types_icons = {}
    for i, id in pairs(hero_types) do
        local meta  = slk.unit[id]
        local data  = setmetatable({}, {__index = meta})
        local primary_names = {STR = '力量型', AGI = '敏捷型', INT = '智力型'}
        data.hero_name      = meta.Propernames:match '([^%,]+)'
        data.primary_name   = primary_names[meta.Primary]
        data.range_name     = meta.weapTp1 == 'normal' and '近战' or meta.rangeN1
        local instruction   = hero_type_instr:gsub('%%(.-)%%', function(name) return data[name] end)

        table.insert(hero_types_icons, ('set udg_touxiang[%d] = %q'):format(i, data.Art))
        table.insert(hero_types_texts, ('set udg_HeoZiFuChuan[%d] = "%s"'):format(i, instruction))
        
        --检查英雄属性
            --技能
            local error_type = {}
            if not meta.abilList:match 'A0NA' or not meta.abilList:match 'A0F5' then
                table.insert(error_type, {id, 'abilList'})
            end
            if tonumber(meta.propWin) ~= 180 then
                table.insert(error_type, {id, 'propWin'})
            end
            if tonumber(meta.orientInterp) ~= 0 then
                table.insert(error_type, {id, 'orientInterp'})
            end
            if tonumber(meta.regenMana) ~= 0 or tonumber(meta.regenHP) ~= 0 or meta.regenType ~= 'none' then
                table.insert(error_type, {id, 'regen'})
            end
            if tonumber(meta.canFlee) ~= 0 then
                table.insert(error_type, {id, 'canFlee'})
            end
            if #error_type ~= 0 then
                local texts = {}
                for _, data in ipairs(error_type) do
                    table.insert(texts, ('Hero state error:[%s][%s]'):format(data[1], data[2]))
                end
                error(table.concat(texts, '\n'))
            end
    end

    --创建反向表(不要吐槽我英文)
	function table.back(t)
		local tt = {}
		for name, value in pairs(t)	do
			if not tt[name] and not tt[value] then
				tt[name]	= true
				tt[value]	= true
				t[value]	= name
			end
		end
		return t
	end

?>
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library defineLibrary
    define{
        void = nothing
        int = integer
        bool = boolean
    }
 #define RELEASE //内测版本请将此行注释

    #ifdef RELEASE
        define <debug@> = /##/
        define <release@> = //
    #else
        define <debug@> = //
        define <release@> = /##/
        define StringHash = StringHash2
    #endif

    define{
        <forGroup>(u,g) = {group localLoopGroup = g;loop;unit u = FirstOfGroup(localLoopGroup);exitwhen u == null;GroupRemoveUnit(localLoopGroup,u)}
        <forGroup>(u,g,b) = {localLoopGroup = g;loop;unit u = FirstOfGroup(localLoopGroup);exitwhen u == null;GroupRemoveUnit(localLoopGroup,u)}
        <endGroup> = {endloop;DestroyGroup(localLoopGroup);localLoopGroup = null}
    }

    define{
        UnitHasBuffBJ(u, id) = (GetUnitAbilityLevel(u, id) == 1)
        UnitRemoveBuffBJ(id, u) = UnitRemoveAbility(u, id)
        <call StartTimerBJ>(t, b, r) = {set bj_lastStartedTimer = t;call TimerStart(bj_lastStartedTimer, r, b, null)}
        <GetLastCreatedTimerDialogBJ()> = bj_lastCreatedTimerDialog
        GetKillingUnitBJ = GetKillingUnit
        <GetPlayersAll()> = bj_FORCE_ALL_PLAYERS
        SetUnitLifeBJ(u, r) = SetUnitState(u, UNIT_STATE_LIFE, r)
        SetUnitManaBJ(u, r) = SetUnitState(u, UNIT_STATE_MANA, r)
        UnitItemInSlotBJ(u, i) = UnitItemInSlot(u, (i) - 1)
        GetAttackedUnitBJ = GetTriggerUnit
        IsUnitPausedBJ(u) = IsUnitPaused(u)
        String2OrderIdBJ(o) = OrderId(o)
        OrderId2StringBJ = OrderId2String
        GetIssuedOrderIdBJ = GetIssuedOrderId
        IsUnitIllusionBJ = IsUnitIllusion
        <call DoNothing()> = { }
        AddUnitAnimationPropertiesBJ(b, s, u) = AddUnitAnimationProperties(u, s, b)
        <GetLastCreatedTextTag()> = bj_lastCreatedTextTag
        TriggerRegisterTimerEventSingle(a, b) = TriggerRegisterTimerEvent(a, b, false)
        ResetUnitAnimation(u) = SetUnitAnimation(u, "stand")
        I2R(i) = {(i)}
        //UnitAddItemByIdSwapped(id, u) = UnitAddItemById(u, id)
    }

    #define YDWEH2I(h) GetHandleId(h)
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library baseLibrary initializer Init needs LuaLibrary

    bool hasLua = false
    bool KoreanVer = false

    struct sys
        static bool JAPI = false
        static player selfp
        static int self
        static group g
        static timer timeTimer = CreateTimer()
        release@    static bool Debug = false
        debug@      static bool Debug = true

        static real getTime(){
            return TimerGetElapsed(timeTimer)
        }

        static gamecache GC = null

        static bool isIn11(){
            return hasLua
        }

        static player firstPlayer = Player(0)

        static bool IsPlayer(player p){
            return GetPlayerController(p)==MAP_CONTROL_USER and GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING
        }

        static void InitFirstPlayer(){
            int i = 0
            loop
                exitwhen i > 11
                if IsPlayer(Player(i)) then
                    firstPlayer = Player(i)
                    return
                endif
                i ++
            endloop
        }

        //-1表示还未检测 0表示游戏 1表示录像
        static int IsReplay = -1

        static real cx = 0
        static real cy = 0

        static void CheckReplayTimed(){
            if not IsPlayer(firstPlayer) then
                DestroyTimer(GetExpiredTimer())
                IsReplay = 0
                if sys.isIn11() then
                    Lua_hook(sys.selfp, "set_replay false")
                endif
                return
            endif

            if GetStoredInteger(GC, "CR", "i") == 0 then
                return
            endif

            real x = GetStoredReal(GC, "CR", "x")
            real y = GetStoredReal(GC, "CR", "y")
            bool hasPlayed = GetStoredBoolean(GC, "CR", "p")

            if sys.selfp == firstPlayer then
                if x != cx or y != cy or hasPlayed != baka.hasPlayed then
                    IsReplay = 1
                    BJDebugMsg("|cffffff00<录像模式>|r")
                    udg_GodView    = true
                    if sys.isIn11() then
                        Lua_hook(sys.selfp, "set_replay true")
                    endif
                else
                    IsReplay = 0
                    udg_GodView    = IsPlayerObserver(sys.selfp)
                    debug@ BJDebugMsg("|cffffff00<游戏模式>|r")
                    if sys.isIn11() then
                        Lua_hook(sys.selfp, "set_replay false")
                    endif
                endif
            else
                IsReplay = 0
                udg_GodView    = IsPlayerObserver(sys.selfp)
                if sys.isIn11() then
                    Lua_hook(sys.selfp, "set_replay false")
                endif
            endif

            DestroyTimer(GetExpiredTimer())
        }

        static void CheckReplay(){
            //通过镜头位置来判断是否为录像
            cx = GetCameraTargetPositionX()
            cy = GetCameraTargetPositionY()

            //只有主机进行同步
            if selfp == firstPlayer then
                StoreReal(GC, "CR", "x", cx)
                StoreReal(GC, "CR", "y", cy)
                StoreBoolean(GC, "CR", "p", baka.hasPlayed)
                StoreInteger(GC, "CR", "i", 1)
                SyncStoredReal(GC, "CR", "x")
                SyncStoredReal(GC, "CR", "y")
                SyncStoredBoolean(GC, "CR", "p")
                SyncStoredInteger(GC, "CR", "i")
                StoreReal(GC, "CR", "x", 0)
                StoreReal(GC, "CR", "y", 0)
                StoreBoolean(GC, "CR", "p", false)
                StoreInteger(GC, "CR", "i", 0)
            endif

            TimerStart(GetExpiredTimer(), 0.1, true, function sys.CheckReplayTimed)
        }
    endstruct

    int H2I(handle h){
        return GetHandleId(h)
    }

//文本宏
    define{
        <toDefine>(a) = toDe##fine(a)
        <call toDefine>(a, b) = {local a udg_##b}
        /*
        令循环整数局部化
        */
        <call toDefine("循环整数A局部化")()> = {int bj_forLoopAIndex,bj_forLoopAIndexEnd}
        <call toDefine("循环整数B局部化")()> = {int bj_forLoopBIndex,bj_forLoopBIndexEnd}
        /*
        令指定变量局部化
        */
        <call toDefine("清空局部变量")()> = {flush locals}
    }

    private void Init(){
        sys.JAPI = GetUnitState(gg_unit_hcas_0015, ConvertUnitState(0x20)) != 0 //同过获取主基地的护甲值来判定是否有JAPI插件(11平台)
        sys.selfp = GetLocalPlayer()
        sys.self = GetPlayerId(sys.selfp)
        TimerStart(sys.timeTimer, 999999, false, null)
        #define udg_GameTimer sys.timeTimer
        //jass与lua公用一个缓存文件,由lua来创建
        if sys.GC == null then
            debug@ BJDebugMsg("缓存文件不存在,新建")
            sys.GC = InitGameCache("U")
        else
            debug@ BJDebugMsg("缓存文件已由Lua创建")
        endif
        //寻找第一个玩家
        sys.InitFirstPlayer()
        //检测录像模式
        TimerStart(CreateTimer(), 3, false, function sys.CheckReplay)
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library YDWELibrary initializer Init needs baseLibrary
    private unit U = null

    private unit Uflush_units[]
    private int Iflush_first = 0
    private int Iflush_top = 0

    void FlushUnit_Add(unit u){
        Uflush_units[Iflush_first] = u
        loop
            Iflush_first ++
            exitwhen Uflush_units[Iflush_first] == null
        endloop
        //BJDebugMsg("first = " + I2S(Iflush_first))
        if Iflush_first > Iflush_top then
            Iflush_top = Iflush_first
        endif
        if Iflush_first > 500 then
            debug@ BJDebugMsg("开始清理单位主键")
            int i = Iflush_top
            int Iflush_count = 0
            loop
                exitwhen i == -1
                U = Uflush_units[i]
                if GetUnitTypeId(U) == 0 then
                    FlushChildHashtable(YDHT, GetHandleId(U))
                    Uflush_units[i] = null
                    Iflush_first = i
                    Iflush_count ++
                endif
                i --
            endloop
            debug@ BJDebugMsg("单位主键清理完毕,共清理 " + I2S(Iflush_count) + " 个主键,新的first为: " + I2S(Iflush_first))
            if Iflush_first > 500 then
                BJDebugMsg("<请截图汇报>单位主键大于500!!!")
                BJDebugMsg("单位类型 [" + I2S(GetUnitTypeId(Uflush_units[GetRandomInt(1, 500)])) + "]")
            else
                GetLocalizedHotkey("yd_leak_monitor::create_report")
            endif
        endif
    }

    private void FlushUnit_Start(){
        U = GetTriggerUnit()
        if GetUnitAbilityLevel(U, 'Aloc') == 0 and (not IsUnitType(U, UNIT_TYPE_HERO) or IsUnitType(U, UNIT_TYPE_SUMMONED)) then
            FlushUnit_Add(U)
        endif
    }

    private void Init(){
        trigger trg = CreateTrigger()
        TriggerRegisterEnterRectSimple(trg, GetWorldBounds())
        TriggerAddCondition(trg, Condition(function FlushUnit_Start))
        trg = null
    }
endlibrary
########
########
//TESH.scrollpos=30
//TESH.alwaysfold=0
library Record initializer Init needs baseLibrary
    globals
        string hke_ZZ=null
        string hke_Z01=null
        string hke_Z11=null
        string hke_Z21=null
        string hke_Z31=null
        string hke_Z41=null
        string hke_Z51=null
        string hke_Z61=null
        string hke_Z71=null
        string hke_Z81=null
        //积分全局变量,别忘了用UTF-8编码
        boolean cheat=false
        player cheatplayer=null
        gamecache array GC
        boolean array runaway
        integer MaxExp=0
        integer PlayerNumber=0
        boolean IsGameOver=false
        integer array TeamPlayer
        boolean isRun=false
        boolean isRun2=false
        unit array BaseUnit
        unit array Hero
        trigger array MU_KillHero
        trigger array MU_DamageHero
        integer array Record
        integer array MU_Assist
        real array DamageTime
        integer array MU_Kill
        integer array MU_Die
        integer array MU_Spell
        integer array MU_NKill
        integer array MU_MKill
        integer array MU_CQ
        integer array MU_Wins
        boolean MVP=false
        integer WinScore=0
        integer LoseScore=0
        boolean KengDie=true
        integer array KDScore
        integer EXP=0
    endglobals
define{
    SetAllItemTypeSlots(i) = GetCH(udg_k,i)
    UnitWakeUp(u) = InitPlayerHero(u)
}
	function I2S2 takes integer i returns string
		return SubString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", i, i + 1)
	endfunction
	//提取数据
	function Get takes integer i,string s returns integer
		Lua_hook(Player(i), "getRecord " + s)
        return udg_Lua_integer
	endfunction
	//储存数据
	function Set takes integer i,string s,integer j returns nothing
		Lua_hook(Player(i), "setRecord " + s + " " + I2S(j))
	endfunction
	//保存积分
	function Save takes nothing returns nothing
		Lua_hook(sys.selfp, "saveRecord")
	endfunction
	//测试用
	function Test2 takes nothing returns boolean
		local unit u=GetTriggerUnit()
		call BJDebugMsg(" ")
		call BJDebugMsg("<单位名称>"+GetUnitName(u))
		call BJDebugMsg("<单位坐标>("+R2S(GetUnitX(u))+","+R2S(GetUnitY(u))+")")
		call BJDebugMsg("<单位类型>"+I2S(GetUnitTypeId(u)))
		call BJDebugMsg("<单位句柄>"+I2S(GetHandleId(u)))
		set u=null
		return false
	endfunction

	function Test3 takes nothing returns boolean
		local unit u=GetTriggerUnit()
		call BJDebugMsg(" ")
		call BJDebugMsg("<单位名称>"+GetUnitName(u))
		call BJDebugMsg("<技能名称>"+GetObjectName(GetSpellAbilityId()))
		call BJDebugMsg("<技能ID>"+I2S(GetSpellAbilityId()))
		set u=null
		return false
	endfunction

    function Test4_1 takes nothing returns boolean
        call KillUnit(GetTriggerUnit())
        call DestroyTrigger(GetTriggeringTrigger())
        return false
    endfunction

	function Test4 takes nothing returns nothing
        local trigger trg = CreateTrigger()
        call TriggerRegisterPlayerSelectionEventBJ(trg, GetTriggerPlayer(), true)
        call TriggerAddCondition(trg, Condition(function Test4_1))
        set trg = null
	endfunction

	function Test takes nothing returns boolean
		local integer x=0
		local integer y=0
		local integer i=0
		local integer j=0
		local string s=GetEventPlayerChatString()
		local string s2=""
		local trigger trg
		if StringCase(s,false)==".save" then
			call Save()
			call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"积分已保存")
		elseif StringCase(SubString(s,0,4),false)==".get" then
			set x=5
			loop
				exitwhen SubString(s,x,x+1)=="" or SubString(s,x,x+1)==" "
				set x=x+1
			endloop
			set i=S2I(SubString(s,5,x))
			set s2=SubString(s,x+1,StringLength(s))
			call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"("+I2S(i)+","+s2+") →→ "+I2S(Get(i,s2)))
		elseif StringCase(SubString(s,0,4),false)==".set" then
			set x=5
			loop
				exitwhen SubString(s,x,x+1)=="" or SubString(s,x,x+1)==" "
				set x=x+1
			endloop
			set i=S2I(SubString(s,5,x))
			set y=x+1
			loop
				exitwhen SubString(s,y,y+1)=="" or SubString(s,y,y+1)==" "
				set y=y+1
			endloop
			set s2=SubString(s,x+1,y)
			set j=S2I(SubString(s,y+1,StringLength(s)))
			call Set(i,s2,j)
			call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,I2S(j)+" →→ ("+I2S(i)+","+s2+")")
		elseif StringCase(s,false)==".info" then
			set trg=CreateTrigger()
			call TriggerRegisterPlayerUnitEvent(trg,GetTriggerPlayer(),EVENT_PLAYER_UNIT_SELECTED,null)
			call TriggerAddCondition(trg,Condition(function Test2))
			set trg=null
		elseif StringCase(s,false)==".skill" then
			set trg=CreateTrigger()
			call TriggerRegisterPlayerUnitEvent(trg,GetTriggerPlayer(),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
			call TriggerAddCondition(trg,Condition(function Test3))
			set trg=null
		elseif StringCase(s,false)==".kill" then
			call Test4()
		elseif StringCase(s,false)==".record" then
			set IsGameOver=false
			call ExecuteFunc("TGameOver")
		elseif StringCase(s,false)==".hotfix" then
			Lua_hook(GetTriggerPlayer(), "hot_fix_ex")
        else
            call TriggerExecute(test.testTrigger)
		endif
		return false
	endfunction

	function InitTest takes nothing returns boolean
		local trigger trg=null
        local string name = sPlayer.base_name[GetPlayerId(GetTriggerPlayer())]

		if GetEventPlayerChatString()=="筒隐月子俺嫁"/*
*/      and StringHash(I2S(GetStoredInteger(sys.GC, "test", I2S(StringHash(name))))) == 2131604752 then
			set trg=CreateTrigger()
			call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"积分测试模式")
			call TriggerRegisterPlayerChatEvent(trg,GetTriggerPlayer(),".",false)
			call TriggerAddCondition(trg,Condition(function Test))
			Lua_hook(GetTriggerPlayer(), "god_mode")
			set trg=null
		endif
		return false
	endfunction
	//压缩数据
	function runawayB2I takes nothing returns nothing
		local integer i=1
		local integer j=1
		local integer result=0
		local integer run=0
		local integer id=GetPlayerId(GetLocalPlayer())
		loop
			exitwhen i>25
			if runaway[i] then
				set result = result+j
				set run = run+2
			endif
			set i=i+1
			set j=j*2
		endloop
		call Set(id,"R1",result)
		set i=1
		set j=1
		set result=0
		loop
			exitwhen i>25
			if runaway[i+25] then
				set result = result+j
				set run = run+2
			endif
			set i=i+1
			set j=j*2
		endloop
		call Set(id,"R2",result)
		call Set(id,"逃跑",run)
	endfunction
	//解压数据
	function runawayI2B takes nothing returns nothing
		local integer i=1
		local integer j=1
		local integer id=GetPlayerId(GetLocalPlayer())
		local integer result=Get(id,"R1")
		loop
			exitwhen i>25
			set j=result/2
			if result==j*2 then
				set runaway[i]=false
			else
				set runaway[i]=true
			endif
			set i=i+1
			set result=j
		endloop
		set i=1
		set j=1
		set result=Get(id,"R2")
		loop
			exitwhen i>25
			set j=result/2
			if result==j*2 then
				set runaway[i+25]=false
			else
				set runaway[i+25]=true
			endif
			set i=i+1
			set result=j
		endloop
	endfunction

	function SetLevel takes nothing returns nothing
		local integer x=Get(sys.self,"经验")
		local integer i=0
		loop
			exitwhen x<(25*i*i+75*i)
			set i=i+1
		endloop
		call Set(sys.self,"等级",i)
	endfunction

	function RunAway takes integer isrun returns nothing
		local integer i = GetPlayerId(GetLocalPlayer())
		local integer j = 1
		if IsPlayerObserver(GetLocalPlayer()) or (IsGameOver and isrun != 1) then
			return
		endif
		if isrun==0 then
			if Get(i,"R0")==50 then
				call Set(i,"R0",1)
			else
				call Set(i,"R0",1+Get(i,"R0"))
			endif
			call runawayI2B()
			set runaway[Get(i,"R0")]=true
			call runawayB2I()
			set isRun=true
			call Set(sys.self,"经验",Get(sys.self,"经验")-100)
		elseif isRun then
			call runawayI2B()
			set runaway[Get(i,"R0")]=false
			call runawayB2I()
			if isrun==1 then
				call Set(sys.self,"经验",Get(sys.self,"经验")+50)
				set isRun2=true
			else
				set isRun=false
				if isRun2 then
					call Set(sys.self,"经验",Get(sys.self,"经验")+50)
				else
					call Set(sys.self,"经验",Get(sys.self,"经验")+100)
				endif
			endif
		endif
		call SetLevel()
		call Save()
	endfunction

	function CountPlayer takes nothing returns boolean
		local integer i=0
		local boolean result=false
		loop
			exitwhen i>11
			if IsPlayerObserver(Player(i))==false and GetPlayerController(Player(i))==MAP_CONTROL_USER and GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING then
				set TeamPlayer[GetPlayerTeam(Player(i))]=TeamPlayer[GetPlayerTeam(Player(i))]+1
			endif
			set i=i+1
		endloop
		set result=(TeamPlayer[0]>0 and TeamPlayer[1]>0)
		set PlayerNumber=TeamPlayer[0]+TeamPlayer[1]
		if PlayerNumber==10 then
			set MVP=true
		endif
		return result
	endfunction

	function MinTimer takes nothing returns nothing
		if IsGameOver or IsPlayerObserver(GetLocalPlayer()) then
			return
		endif
		call Set(sys.self,"时间",1+Get(sys.self,"时间"))
		call Save()
	endfunction

	function GameOver takes integer tid returns nothing
		local integer i=1
		local integer j=GetPlayerId(GetLocalPlayer())
		local integer x
		local integer y
		if IsGameOver or IsPlayerObserver(GetLocalPlayer()) then
			return
		endif
		call RunAway(2)
		set IsGameOver=true
		if sys.getTime()<600 or tid<0 then
			call Set(sys.self,"局数",Get(sys.self,"局数")-1)
			call Set(sys.self,"经验",Get(sys.self,"经验")-LoseScore-KDScore[j])
            call Set(sys.self, "连胜", MU_Wins[j])
			call SetLevel()
			if Get(sys.self,"局数")==0 then
				call Set(sys.self,"胜率",0)
			else
				call Set(sys.self,"胜率",100*Get(sys.self,"胜利") / IMaxBJ(Get(sys.self,"局数"), 1))
			endif
			call Save()
			if sys.getTime()<600 then
				call BJDebugMsg("|cff008800游戏时间不足10分钟,不计胜负|r")
			else
				call BJDebugMsg("|cff008800测试模式启动,积分已被关闭|r")
			endif
			return
		endif
        Lua_hook(sys.selfp, "game_over " + I2S(tid))
        set x=0
		set i=0
		loop
			exitwhen i>9
			if MU_Assist[i]>x then
				set x=MU_Assist[i]
			endif
			set i=i+1
		endloop
		if x>30 then //KD分至少达到50,且为5V5才能拿MVP
			set i=0
			loop
				exitwhen i>9
				if MU_Assist[i]==x then
					call Set(i,"助攻王",1+Get(i,"助攻王"))
					call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,GetPlayerName(Player(i))+"|cff008800获得了荣誉：|cffffff00助攻王|r")
					set Record[i]=Record[i]+10
				endif
				set i=i+1
			endloop
		endif
		//兼容SP模式
		i = 0
		int MU_Score[]
		loop
			exitwhen i > 9
			MU_Score[i] = udg_Score[baka.spid[i] + 1]
			i ++
		endloop
		//
		set x=0
		set i=0
		loop
			exitwhen i>9
			if MU_Score[i]>x then
				set x=MU_Score[i]
			endif
			set i=i+1
		endloop
		if x>3000 and MVP then //至少达到3000分,且为5V5才能拿MVP
			set i=0
			loop
				exitwhen i>9
				if MU_Score[i]==x then
					call Set(i,"MVP",1+Get(i,"MVP"))
					call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,GetPlayerName(Player(i))+"|cff008800获得了荣誉：|cffffff00MVP|r")
					set Record[i]=Record[i]+30
				endif
				set i=i+1
			endloop
		endif
		if IsUnitAlly(BaseUnit[tid],Player(j)) then
			call Set(j,"胜利",Get(j,"胜利")+1)
            call Set(j, "连胜", 1+MU_Wins[j])
			set Record[j]=Record[j]+WinScore
			//set Record[j]=Record[j]+200 //额外经验
		else
			set Record[j]=Record[j]+LoseScore
			//set Record[j]=Record[j]+100 //额外经验
		endif
		set Record[j]=Record[j]+KDScore[j]
		call Set(sys.self,"胜率",100*Get(sys.self,"胜利") / IMaxBJ(Get(sys.self,"局数"), 1))
        if MU_Score[j+1] > Get(sys.self, "纪录") then
            call DisplayTimedTextToPlayer(Player(j),0,0,60,"|cff00ff00你刷新了自己的最高积分纪录|r(|cffffcc00"+I2S(Get(sys.self, "纪录"))+"|r)|cff00ff00!!
新的纪录为|cffffcc00"+I2S(MU_Score[j+1])+"|cff00ff00分!!|r")
            call Set(sys.self, "纪录", MU_Score[j+1])
        endif
		if Record[j]>MaxExp then
			set Record[j]=MaxExp
		endif
		if Record[j]>=0 then
			//call DisplayTimedTextToPlayer(Player(j),0,0,60,"|cff00ff00经验+"+I2S(Record[j])+"|r")
		else
			//call DisplayTimedTextToPlayer(Player(j),0,0,60,"|cff00ff00经验"+I2S(Record[j])+"|r")
		endif
		call Set(sys.self,"经验",Record[j]-LoseScore-KDScore[j]+Get(sys.self,"经验"))
		call SetLevel()
		call Save()
		call BJDebugMsg("|cffcc00ff积分已保存|r")
	endfunction

	function GetCH takes unit u,integer s returns nothing
		local integer i=GetPlayerId(GetOwningPlayer(u))
		if IsGameOver then
			return
		endif
		call Set(i,"荣誉",Get(i,"荣誉")+s)
		call Set(i,"经验",Get(i,"经验")+s)
        if s == 16 then
            call Set(i, "战神",1+Get(i, "战神"))
        endif
		set KDScore[i]=KDScore[i]+s
		call SetLevel()
		call Save()
	endfunction

	function TGameOver takes nothing returns nothing
		call GameOver(GetPlayerTeam(GetTriggerPlayer()))
	endfunction

	function PlayerLeave takes nothing returns boolean
		if IsPlayerObserver(GetTriggerPlayer()) or IsGameOver then
			return false
		endif
		set KengDie=false
		set TeamPlayer[GetPlayerTeam(GetTriggerPlayer())]=TeamPlayer[GetPlayerTeam(GetTriggerPlayer())]-1
		set PlayerNumber=PlayerNumber-1
		if TeamPlayer[0]==0 then
			//call GameOver(1)
		elseif TeamPlayer[1]==0 then
			//call GameOver(0)
		endif
		call RunAway(2)
		return false
	endfunction

	function KillHero takes nothing returns boolean
        local integer id1
        local integer id2=GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
        local unit u
        local integer i=0
        if IsPlayerObserver(Player(id2)) or IsGameOver or GetPlayerController(Player(id2))!=MAP_CONTROL_USER or GetPlayerSlotState(Player(id2))!=PLAYER_SLOT_STATE_PLAYING then
            return false
        endif
        set MU_Die[id2]=MU_Die[id2]+1
        set KDScore[id2]=KDScore[id2]-3
        call Set(id2,"经验",Get(id2,"经验")-3)
        call Set(id2,"死亡",Get(id2,"死亡")+1)
        call SetLevel()
        //call Save()
        if GetKillingUnit()==null then
            return false
        endif
        set id1=GetPlayerId(GetOwningPlayer(GetKillingUnit()))
        set u=GetTriggerUnit()
        if IsUnitEnemy(u,Player(id1)) then
            set KDScore[id1]=KDScore[id1]-IMinBJ(50,5*MU_NKill[id1])
            call Set(id1,"经验",Get(id1,"经验")-IMinBJ(50,5*MU_NKill[id1]))
            set MU_Kill[id1]=MU_Kill[id1]+1
            set MU_NKill[id1]=MU_NKill[id1]+1
            if MU_NKill[id1]>MU_MKill[id1] then
                set MU_MKill[id1]=MU_NKill[id1]
            endif
            if MU_MKill[id1]>Get(id1,"MK") then
                call Set(id1,"MK",MU_MKill[id1])
            endif
            set KDScore[id1]=KDScore[id1]+1
            call Set(id1,"经验",Get(id1,"经验")+1)
            set KDScore[id1]=KDScore[id1]+IMinBJ(50,5*MU_NKill[id1])
            call Set(id1,"经验",Get(id1,"经验")+IMinBJ(50,5*MU_NKill[id1]))
            call Set(id1,"杀敌",Get(id1,"杀敌")+1)
            set MU_NKill[id2]=0
            loop
                exitwhen i>9
                if i!=id1 and IsPlayerEnemy(Player(id2),Player(i)) and sys.getTime()-DamageTime[i*100+id2]<15 then
                    set MU_Assist[i]=MU_Assist[i]+1
                    set KDScore[i]=KDScore[i]+3
                    call Set(i,"经验",Get(i,"经验")+3)
                    call Set(i,"助攻",Get(i,"助攻")+1)
                endif
                set i=i+1
            endloop
        endif
        call SetLevel()
        //call Save()
        set u=null
        return false
    endfunction

	function DamageHero takes nothing returns boolean
		local integer id1=GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
		local integer id2=GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
		set DamageTime[id1*100+id2]=sys.getTime()
		return false
	endfunction

	function InitPlayerHero takes unit hero returns nothing
		local integer id=GetPlayerId(GetOwningPlayer(hero))
        baka.InitHero(hero) //专用库注册英雄
		if IsGameOver then
			return
		endif
		//call BJDebugMsg("注册英雄"+GetUnitName(hero))
		set Hero[id]=hero
		call DestroyTrigger(MU_KillHero[id])
		set MU_KillHero[id]=CreateTrigger()
		call TriggerRegisterUnitEvent(MU_KillHero[id],hero,EVENT_UNIT_DEATH)
		call TriggerAddCondition(MU_KillHero[id],Condition(function KillHero))
		call DestroyTrigger(MU_DamageHero[id])
		set MU_DamageHero[id]=CreateTrigger()
		call TriggerRegisterUnitEvent(MU_DamageHero[id],hero,EVENT_UNIT_DAMAGED)
		call TriggerAddCondition(MU_DamageHero[id],Condition(function DamageHero))
	endfunction

	function IsUnitDead takes unit u returns boolean
		return u==null or IsUnitType(u,UNIT_TYPE_DEAD)
	endfunction

	function BuildingDestroy takes nothing returns boolean
		local integer i
		local integer j
		if IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetKillingUnit(),GetOwningPlayer(GetTriggerUnit())) then
			set i=GetUnitTypeId(GetTriggerUnit())
			set j=GetPlayerId(GetOwningPlayer(GetKillingUnit()))
			set MU_CQ[j]=MU_CQ[j]+1
		endif
		return false
	endfunction

	function BaseDestroy takes nothing returns boolean
		if GetTriggerUnit()==BaseUnit[0] then
			//call GameOver(1)
		else
			//call GameOver(0)
		endif
		return false
	endfunction

	function RunA takes nothing returns nothing
		local integer i=0
		local real r1=0
		local real r2=0
        if IsGameOver
            return
        endif
		call SetLevel()
		call RunAway(0)
		loop
			exitwhen i>11
			if i!=5 and i!=11 then
				if IsPlayerEnemy(GetLocalPlayer(),Player(i)) then
					set r2=r2+I2R(Get(i,"等级"))
				else
					set r1=r1+I2R(Get(i,"等级"))
				endif
			endif
			set i=i+1
		endloop
		set r1=r2/5.-(r1+I2R(5*Get(sys.self,"等级")))/10.
		if r1>0 then
			set WinScore=R2I(100*Sin(RMinBJ(r1,10)*3.1416/20)+50)
			set LoseScore=R2I(100*Sin(RMinBJ(r1,10)*3.1416/20)-50)
		else
			set WinScore=R2I(50*Sin(RMaxBJ(r1,-20)*3.1416/40)+50)
			set LoseScore=R2I(100*Sin(RMaxBJ(r1,-15)*3.1416/30)-50)
		endif
		if WinScore<1 then
			set WinScore=1
		endif
		if LoseScore<-150 then
			set LoseScore=-150
		endif
        set MU_Wins[GetPlayerId(GetLocalPlayer())] = Get(sys.self, "连胜")
		call Set(sys.self,"经验",Get(sys.self,"经验")+LoseScore)
		call SetLevel()
		if not IsPlayerObserver(GetLocalPlayer()) then
			call Set(sys.self,"局数",Get(sys.self,"局数")+1)
			call Set(sys.self,"胜率",100*Get(sys.self,"胜利")/Get(sys.self,"局数"))
            call Set(sys.self,"连胜", 0)
		endif
		call Save()
	endfunction

	function RunB takes nothing returns nothing
		call DestroyTimer(GetExpiredTimer())
		set MaxExp=999999
		call RunAway(1)
	endfunction
	//注册
	function InitRecord takes nothing returns nothing
		local integer i=0
		local trigger trg=CreateTrigger()
		local real r1=0
		local real r2=0
		local integer rs=0
		call DestroyTimer(GetExpiredTimer())
        set IsGameOver = true
		loop
			exitwhen i>15
			if IsPlayerObserver(Player(i)) then
				set GC[i]=InitGameCache("Nothing")
			else
				set GC[i]=InitGameCache("11SAV@"+I2S2(i))
			endif
			call Lua_hook(Player(i),"setGC "+I2S(GetHandleId(GC[i])))
			call TriggerRegisterPlayerChatEvent(trg,Player(i),"",false)
			set i=i+1
		endloop
		call TriggerAddCondition(trg,Condition(function InitTest))
		call StoreString(GC[sys.self],"","Title@"+I2S2(0),"局数")
		call StoreString(GC[sys.self],"","Title@"+I2S2(1),"连胜")
		call StoreString(GC[sys.self],"","Title@"+I2S2(2),"助攻王")
		call StoreString(GC[sys.self],"","Title@"+I2S2(3),"节操")
		call StoreString(GC[sys.self],"","Title@"+I2S2(4),"胜率")
		call StoreString(GC[sys.self],"","Title@"+I2S2(5),"战神")
		call StoreString(GC[sys.self],"","Title@"+I2S2(6),"逃跑")
		call StoreString(GC[sys.self],"","Title@"+I2S2(7),"MVP")
        if not sys.JAPI then
            return
        endif
        Lua_hook(sys.selfp, "initRecord")
        set IsGameOver = false
		call TimerStart(CreateTimer(),1200,false,function RunB)
		call TimerStart(CreateTimer(),60,true,function MinTimer)
		set trg=CreateTrigger()
		set i=0
		loop
			exitwhen i>11
			call TriggerRegisterPlayerEvent(trg,Player(i),EVENT_PLAYER_LEAVE)
			set i=i+1
		endloop
		call TriggerAddCondition(trg,Condition(function PlayerLeave))
		set BaseUnit[0]=gg_unit_hcas_0015
		set BaseUnit[1]=gg_unit_hcas_0020
		//call BJDebugMsg(GetUnitName(BaseUnit[0]))
		//call BJDebugMsg(GetUnitName(BaseUnit[1]))
		set trg=CreateTrigger()
		call TriggerRegisterUnitEvent(trg,BaseUnit[0],EVENT_UNIT_DEATH)
		call TriggerRegisterUnitEvent(trg,BaseUnit[1],EVENT_UNIT_DEATH)
		call TriggerAddCondition(trg,Condition(function BaseDestroy))
		set trg=CreateTrigger()
		call TriggerRegisterPlayerUnitEvent(trg,GetOwningPlayer(BaseUnit[0]),EVENT_PLAYER_UNIT_DEATH,null)
		call TriggerRegisterPlayerUnitEvent(trg,GetOwningPlayer(BaseUnit[1]),EVENT_PLAYER_UNIT_DEATH,null)
		call TriggerAddCondition(trg,Condition(function BuildingDestroy))
		set trg=null
        
        //写入本地存档
        Get(sys.self, "局数")
        Get(sys.self, "连胜")
        Get(sys.self, "助攻王")
        Get(sys.self, "节操")
        Get(sys.self, "胜率")
        Get(sys.self, "战神")
        Get(sys.self, "逃跑")
        Get(sys.self, "MVP")
        Get(sys.self, "胜利")
        Get(sys.self, "经验")
        Get(sys.self, "等级")
        Get(sys.self, "杀敌")
        Get(sys.self, "助攻")
        Get(sys.self, "死亡")
        Get(sys.self, "荣誉")
        Get(sys.self, "战神")
        Get(sys.self, "纪录")
        Get(sys.self, "时间")
        Get(sys.self, "R0")
        Get(sys.self, "R1")
        Get(sys.self, "R2")

        //Set(sys.self,"V",4) --被下面的函数取代
        if not baka.newMap() then
            call Save()
            set IsGameOver = true
            return
        endif
		if not CountPlayer() then
			call Save()
			release@ set IsGameOver=true
			release@ return
		endif
        release@ RunA()
        //set MVP = true //test
		call BJDebugMsg("|cffcc00ff积分系统已经开启，游戏结束后请在屏幕上显示“积分已保存”后再离开游戏")
		//call BJDebugMsg("|cffcc00ff该版本为2.5D正式版.游戏结束时,你可以额外获得200(胜)/100(负)的经验")
		call Save()
		//call BJDebugMsg("积分初始化完成")
	endfunction

	private void Init(){
		call TimerStart(CreateTimer(),0,false,function InitRecord)
	}
endlibrary
########
########
//TESH.scrollpos=140
//TESH.alwaysfold=0
//直接挂载YDWE的伤害事件
#include "YDWETriggerEvent.j"

library eventLibrary initializer Init needs baseLibrary

    struct Event
        static hashtable HT = InitHashtable()
        
        static int index = -1
        static unit u_from[]
        static unit u_to[]
        /*
        跳过自定义事件的剩余触发
        */
        static bool event_skip[]
        
        static void SkipTriggers(){
            event_skip[index] = true
        }
        
        /*
        阻止当前模块发动
        */
        static bool enable_module = true
        
        static void BlockCurrentModule(){
            enable_module = false
        }

        /*
        任意单位发动指定技能事件
        同一个组合内只能保存一个触发器
        */

        static void AnyUnitSkill(trigger trg, int i, int id){
            SaveTriggerHandle(HT, i, id, trg)
        }

        static void skillEventAction(){
            eventid id = GetTriggerEventId()
            trigger trg
            if id == EVENT_PLAYER_UNIT_SPELL_CHANNEL
                trg = LoadTriggerHandle(HT, 1, GetSpellAbilityId())
            elseif id == EVENT_PLAYER_UNIT_SPELL_CAST
                trg = LoadTriggerHandle(HT, 2, GetSpellAbilityId())
            elseif id == EVENT_PLAYER_UNIT_SPELL_EFFECT
                trg = LoadTriggerHandle(HT, 3, GetSpellAbilityId())
            elseif id == EVENT_PLAYER_UNIT_SPELL_ENDCAST
                trg = LoadTriggerHandle(HT, 4, GetSpellAbilityId())
            elseif id == EVENT_PLAYER_UNIT_SPELL_FINISH
                trg = LoadTriggerHandle(HT, 5, GetSpellAbilityId())
            endif
            if trg != null and IsTriggerEnabled(trg) and TriggerEvaluate(trg)
                TriggerExecute(trg)
            endif
            id = null
            trg = null
        }

        static void initSkillEvent(){
            trigger trg = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_CAST)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_FINISH)
            TriggerAddCondition(trg, Condition(function Event.skillEventAction))
            trg = null
        }

        /*
        任意单位获得指定技能事件
        一个技能下只能保存一个触发器
        */

        static void GetSkill(trigger trg, int id){
            SaveTriggerHandle(HT, StringHash("获得技能事件"), id, trg)
        }

        static void GetSkill_Action(){
            trigger trg = LoadTriggerHandle(HT, StringHash("获得技能事件"), GetSpellAbilityId())
            if trg != null and IsTriggerEnabled(trg) and TriggerEvaluate(trg) then
                TriggerExecute(trg)
            endif
            trg = null
        }

        static void initGetSkill(){
            return //暂不使用
            trigger trg = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_HERO_SKILL)
            TriggerAddCondition(trg, Condition(function Event.GetSkill_Action))
            trg = null
        }

        /*
        任意伤害事件
        */

        static trigger damageEventTrigger1[]
        static trigger damageEventTrigger2[]
        static trigger damageEventTrigger3[]
        static trigger damageEventTrigger4[]
        static trigger damageEventTrigger5[]
        static trigger damageEventTrigger6[]
        static trigger damageEventTrigger7[]
        static trigger damageEventTrigger8[]
        static int damageCount1 = 0
        static int damageCount2 = 0
        static int damageCount3 = 0
        static int damageCount4 = 0
        static int damageCount5 = 0
        static int damageCount6 = 0
        static int damageCount7 = 0
        static int damageCount8 = 0

        //任意单位/英雄/非英雄 受到 任意伤害/攻击伤害/非攻击伤害/致命伤害/暴击伤害
        static void AnyUnitDamage(trigger trg, int i1, int i2){
            bool hero, nothero, attack, notattack, dying, crit
            if i1 == 0 then
                hero = true
                nothero = true
            elseif i1 == 1 then
                hero = true
                nothero = false
            elseif i1 == 2 then
                hero = false
                nothero = true
            endif
            if i2 == 0 then
                attack = true
                notattack = true
                dying = false
                crit = false
            elseif i2 == 1 then
                attack = true
                notattack = false
                dying = false
                crit = false
            elseif i2 == 2 then
                attack = false
                notattack = true
                dying = false
                crit = false
            elseif i2 == 3 then
                attack = false
                notattack = false
                dying = true
                crit = false
            elseif i2 == 4 then
                attack = false
                notattack = false
                dying = false
                crit = true
            endif
            int h = GetHandleId(trg)
            SaveInteger(HT, h, 0, 1)
            define define_InitTrigger(n) = {
                damageEventTrigger##n[++ damageCount##n] = trg
                SaveInteger(HT, h, n, 1)
            }
            if hero then
                if attack then
                    define_InitTrigger(1)
                endif
                if notattack then
                    define_InitTrigger(2)
                endif
                if dying then
                    define_InitTrigger(5)
                endif
                if crit then
                    define_InitTrigger(7)
                endif
            endif
            if nothero then
                if attack then
                    define_InitTrigger(3)
                endif
                if notattack then
                    define_InitTrigger(4)
                endif
                if dying then
                    define_InitTrigger(6)
                endif
                if crit then
                    define_InitTrigger(8)
                endif
            endif

            undef define_InitTrigger
        }
        
        static real damage_reduce[]

        static void damageReduce2(){
            timer t = CreateTimer()
            int h = GetHandleId(t)
            UnitAddAbility(u_to[index], 'A0RJ')
            SaveUnitHandle(YDHT, h, 0, u_to[index])
            TimerStart(t, 0, false, \
                lambda void(){
                    timer t = GetExpiredTimer()
                    int h = GetHandleId(t)
                    unit u = LoadUnitHandle(YDHT, h, 0)
                    real hp = GetUnitState(u, UNIT_STATE_LIFE)
                    DestroyTimer(t)
                    FlushChildHashtable(YDHT, h)
                    UnitRemoveAbility(u, 'A0RJ')
                    SetUnitState(u, UNIT_STATE_LIFE, hp)
                    u = null
                    t = null
                }\
            )
            t = null
        }

        static void damageReduce(){
            real reduce = damage_reduce[index]
            real damage = GetEventDamage()
            if reduce > damage then
                reduce = damage
            endif
            real life = GetUnitState(u_to[index], UNIT_STATE_LIFE) + reduce
            if life > GetUnitState(u_to[index], UNIT_STATE_MAX_LIFE) then
                //血牌法抵挡伤害
                damageReduce2()
            endif
            SetUnitState(u_to[index], UNIT_STATE_LIFE, life)
            damage_reduce[index] = 0
        }

        static bool damageEvent_need_clear1 = false
        static bool damageEvent_need_clear2 = false
        static bool damageEvent_need_clear3 = false
        static bool damageEvent_need_clear4 = false
        static bool damageEvent_need_clear5 = false
        static bool damageEvent_need_clear6 = false
        static bool damageEvent_need_clear7 = false
        static bool damageEvent_need_clear8 = false

        static bool damageEvent_Enable = true
        
        define define_TriggerExecute(n) = {
            i = 1

            //检查是否要清理触发器
release@    if damageEvent_need_clear##n and index == 0 then
debug@      if damageEvent_need_clear##n then
debug@          if index != 0 then
debug@              BJDebugMsg("<清理伤害事件>被跳过")
debug@          else
                damageEvent_need_clear##n = false
                int x = 0
                loop
                    exitwhen i > damageCount##n
                    if damageEventTrigger##n[i] == null then
                        x ++
                    elseif x != 0 then
                        damageEventTrigger##n[i - x] = damageEventTrigger##n[i]
                    endif
                    i ++
                endloop
                damageCount##n -= x
                i = 1
debug@          endif
            endif

            //循环运行触发器
            event_skip[index] = false
            loop
                exitwhen i > damageCount##n or event_skip[index]
                if IsTriggerEnabled(damageEventTrigger##n[i]) and TriggerEvaluate(damageEventTrigger##n[i]) then
                    TriggerExecute(damageEventTrigger##n[i])
                endif
                i ++
            endloop
        }
        
        //检查是否是暴击
        static void CheckCrit(bool isHero){
            
            //检查目标合法性
            if IsUnitType(u_to[index], UNIT_TYPE_STRUCTURE) then
                SaveReal(YDHT, StringHash("事件返回"), StringHash("倍率"), 1)
                return
            endif
            
            int i
            int h = GetHandleId(u_from[index])
            int count
            real chance
            real rate
            trigger trg
            real thisRate = 0
            real exRate = LoadReal(YDHT, GetHandleId(u_from[index]), StringHash("暴击倍率加成"))
            real maxRate = 1 + LoadReal(YDHT, h, StringHash("暴击几率加成")) + LoadReal(YDHT, GetHandleId(u_to[index]), StringHash("被暴击几率加成"))
            //检查被暴击几率是否小于0
            if maxRate <= 0 then
                maxRate = -1
            else
                maxRate = 100 / maxRate
            endif
            //取出暴击模块
            count = LoadInteger(YDHT, h, StringHash("暴击模块计数"))
            if maxRate!=-1 && count != 0 then
                //循环遍历暴击模块
                i = 0
                loop
                    exitwhen i > count
                    
                    chance = LoadReal(YDHT, h, StringHash("暴击几率值段") + i)
                    rate   = LoadReal(YDHT, h, StringHash("暴击倍率值段") + i)
                    
                    //判定是否发动该暴击
                    if chance >= GetRandomReal(0, maxRate) then
                    
                        //回调触发
                        trg = LoadTriggerHandle(YDHT, h, StringHash("暴击触发值段") + i)
                        if trg != null then
                            SaveReal(YDHT, StringHash("事件返回"), StringHash("暴击倍率加成"), 0)
                            if IsTriggerEnabled(trg) and TriggerEvaluate(trg) then
                                TriggerExecute(trg)
                            endif
                            exRate += LoadReal(YDHT, StringHash("事件"), StringHash("暴击倍率加成"))
                        endif
                        trg = null
                        
                        if enable_module then
                            //同时暴击取最高值
                            if rate > thisRate then
                                thisRate = rate
                            endif
                        else
                            enable_module = true
                        endif
                        
                    endif
                    
                    i ++
                endloop
            endif
            
            //取出被暴击模块
            h     = GetHandleId(u_to[index])
            count = LoadInteger(YDHT, h, StringHash("被暴击模块计数"))
            if maxRate!=-1 && count != 0 then
                //循环遍历暴击模块
                i = 0
                loop
                    exitwhen i > count
                    
                    chance = LoadReal(YDHT, h, StringHash("被暴击几率值段") + i)
                    rate   = LoadReal(YDHT, h, StringHash("被暴击倍率值段") + i)
                    
                    //判定是否发动该暴击
                    if chance >= GetRandomReal(0, maxRate) then
                    
                        //回调触发
                        trg = LoadTriggerHandle(YDHT, h, StringHash("被暴击触发值段") + i)
                        if trg != null then
                            SaveReal(YDHT, StringHash("事件返回"), StringHash("暴击倍率加成"), 0)
                            if IsTriggerEnabled(trg) and TriggerEvaluate(trg) then
                                TriggerExecute(trg)
                            endif
                            exRate += LoadReal(YDHT, StringHash("事件"), StringHash("暴击倍率加成"))
                        endif
                        trg = null
                        
                        if enable_module then
                            //同时暴击取最高值
                            if rate > thisRate then
                                thisRate = rate
                            endif
                        else
                            enable_module = true
                        endif
                        
                    endif
                    
                    i ++
                endloop
            endif
            
            //是否发动了暴击
            if thisRate == 0 then
                SaveReal(YDHT, StringHash("事件返回"), StringHash("倍率"), 1)
                return
            endif
            
            thisRate += exRate

            //发起暴击事件
            SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "暴击伤害")
            SaveReal(YDHT, StringHash("事件返回"), StringHash("倍率"), thisRate)
            if isHero then
                define_TriggerExecute(7)
            else
                define_TriggerExecute(8)
            endif
            SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "")
            
            //造成暴击伤害
            UnitDamageTarget(u_from[index], u_to[index], GetEventDamage() * (thisRate - 1), false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_ENHANCED, WEAPON_TYPE_WHOKNOWS)
        }

        static void damageEventAction(){
            if GetEventDamage() == 0 or not damageEvent_Enable then
                return
            endif

            int i
            index ++
            u_from[index] = GetEventDamageSource()
            u_to[index] = GetTriggerUnit()
            bool attack
            if UnitRemoveAbility(u_to[index], 'B039') then
                attack = true
                UnitRemoveAbility(u_to[index], 'A0OB')
            else
                attack = UnitRemoveAbility(u_to[index], 'A0OB')
            endif

            real life

            if IsUnitType(u_to[index], UNIT_TYPE_HERO) and not IsUnitType(u_to[index], UNIT_TYPE_SUMMONED) then
                if attack then
                    CheckCrit(true) //检查是否是暴击
                    SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "攻击伤害")
                    define_TriggerExecute(1)
                else
                    call SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "非攻击伤害")
                    define_TriggerExecute(2)
                endif
                //检查是否致命
                life    = GetWidgetLife(u_to[index])
                if life + damage_reduce[index] - GetEventDamage() < 0.5 then
                    SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "致命伤害")
                    define_TriggerExecute(5)
                    if event_skip[index] then
                        damage_reduce[index] = GetEventDamage() - life + 0.5
                    endif
                endif
            else
                if attack then
                    CheckCrit(false) //检查是否是暴击
                    SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "攻击伤害")
                    define_TriggerExecute(3)
                else
                    SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "非攻击伤害")
                    define_TriggerExecute(4)
                endif
                //检查是否致命
                life    = GetWidgetLife(u_to[index])
                if life + damage_reduce[index] - GetEventDamage() < 0.5 then
                    SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "致命伤害")
                    define_TriggerExecute(6)
                    if event_skip[index] then
                        damage_reduce[index] = GetEventDamage() - life + 0.5
                    endif
                endif
            endif
            SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "")

            undef define_TriggerExecute

            if damage_reduce[index] != 0 then
                damageReduce()
            endif

            index --
        }

        static void ReduceDamage(real r){
            damage_reduce[index] += r
        }

        //重置伤害来源
        static unit Damage_from = null
        static unit Real_damage_from = null

        static unit GetDamageFrom(){
            Damage_from = GetEventDamageSource()

            if Damage_from == null then
                return null
            endif

            Real_damage_from = LoadUnitHandle(YDHT, GetHandleId(Damage_from), StringHash("真实伤害来源"))
            if Real_damage_from == null then
                return Damage_from
            endif

            return Real_damage_from
        }
        
        static unit GetOriginDamageFrom(){
            return GetEventDamageSource()
        }
        
        #define GetEventDamageSource() Event.GetDamageFrom()
        
        //获取当前伤害
        static real GetCurrentDamage(){
            return GetEventDamage() - damage_reduce[index]
        }

        static void DamageEventDestroy(trigger trg, int h){
            if LoadInteger(HT, h, 0) == 1 then
                int i1 = LoadInteger(HT, h, 1)
                int i2 = LoadInteger(HT, h, 2)
                int i3 = LoadInteger(HT, h, 3)
                int i4 = LoadInteger(HT, h, 4)
                int i5 = LoadInteger(HT, h, 5)
                int i6 = LoadInteger(HT, h, 6)
                int i7 = LoadInteger(HT, h, 7)
                int i8 = LoadInteger(HT, h, 8)

                define define_DestroyTrigger(n) = {
                    if i##n == 1 then
                        loop
                            exitwhen i##n > damageCount##n
                            if trg == damageEventTrigger##n[i##n] then
                                damageEventTrigger##n[i##n] = null
                                i##n = damageCount##n
                                damageEvent_need_clear##n = true
                            endif
                            i##n ++
                        endloop
                    endif
                }

                define_DestroyTrigger(1)

                define_DestroyTrigger(2)

                define_DestroyTrigger(3)

                define_DestroyTrigger(4)

                define_DestroyTrigger(5)

                define_DestroyTrigger(6)
                
                define_DestroyTrigger(7)
                
                define_DestroyTrigger(8)

                undef define_DestroyTrigger
            endif
        }

        static void initDamageEvent(){
            //直接挂载YD的伤害事件
            TimerStart(CreateTimer(), 0, false,\
                lambda void(){
                    DestroyTimer(GetExpiredTimer())
                    set yd_DamageEventTrigger = CreateTrigger()
                    call TriggerAddAction(yd_DamageEventTrigger, function Event.damageEventAction)
                    call YDWEAnyUnitDamagedEnumUnit()
                }\
            )
        }

        /*
        技能重置事件
        */
        static int SkillCoolReset_skills[]
        static trigger SkillCoolReset_trgs[]
        static int SkillCoolReset_skills_top = 0
        static bool SkillCoolReset_need_clear = false
        static int SkillCoolReset_index = -1

        static void SkillCoolReset(trigger trg, int sid){
            SkillCoolReset_skills_top ++
            SkillCoolReset_skills[SkillCoolReset_skills_top] = sid
            SkillCoolReset_trgs[SkillCoolReset_skills_top] = trg

            //记录
            SaveBoolean(HT, GetHandleId(trg), StringHash("技能重置事件"), true)
        }

        static void UnitResetCooldown_Hook(unit u, int sid){
            if sid == 0 then
                UnitResetCooldown(u)
            endif
            int i = 1
            index ++
            SkillCoolReset_index ++
release@    if SkillCoolReset_need_clear and index == 0 then
debug@      if SkillCoolReset_need_clear then
debug@          if SkillCoolReset_index != 0 then
debug@              BJDebugMsg("<清理冷却事件>被跳过")
debug@          else
                SkillCoolReset_need_clear = false
                int x = 0
                loop
                    exitwhen i > SkillCoolReset_skills_top
                    if SkillCoolReset_trgs[i] == null then
                        x ++
                    elseif x != 0 then
                        SkillCoolReset_trgs[i - x] = SkillCoolReset_trgs[i]
                        SkillCoolReset_skills[i - x] = SkillCoolReset_skills[i]
                    endif
                    i ++
                endloop
                SkillCoolReset_skills_top -= x
                i = 1
debug@          endif
            endif

            event_skip[index] = false
            loop
                exitwhen i > SkillCoolReset_skills_top or event_skip[index]
                if (sid == 0 or sid == SkillCoolReset_skills[i]) and GetUnitAbilityLevel(u, SkillCoolReset_skills[i]) != 0 and IsTriggerEnabled(SkillCoolReset_trgs[i]) then
                    u_from[index] = u
                    u_to[index] = u
                    if TriggerEvaluate(SkillCoolReset_trgs[i]) then
                        TriggerExecute(SkillCoolReset_trgs[i])
                    endif
                endif
                u_from[index] = null
                u_to[index] = null
                i ++
            endloop
            index --
            SkillCoolReset_index --
        }

        #define UnitResetCooldown(u) Event.UnitResetCooldown_Hook(u, 0)

        static void SkillCoolEventDestroy(trigger trg, int h){
            if LoadBoolean(HT, h, StringHash("技能重置事件")) then
                int i = 1
                loop
                    exitwhen i > SkillCoolReset_skills_top
                    if SkillCoolReset_trgs[i] == trg then
                        SkillCoolReset_trgs[i] = SkillCoolReset_trgs[SkillCoolReset_skills_top]
                        i = SkillCoolReset_skills_top
                        SkillCoolReset_need_clear = true
                    endif
                    i ++
                endloop
            endif
        }

        /*
        物品获得
        */

        static void ItemPick(trigger trg, int iid){
debug@      if LoadTriggerHandle(HT, StringHash("英雄获得物品"), iid) != null then
debug@          Lua_hook(sys.selfp, "print Error_event_ItemPick " + I2S(iid))
debug@      endif
            SaveTriggerHandle(HT, StringHash("英雄获得物品"), iid, trg)
        }

        static void initItemPick(){
            trigger trg = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_PICKUP_ITEM)
            TriggerAddCondition(trg, Condition( \
                lambda void(){
                    if not IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
                        return
                    endif
                    trigger trg = LoadTriggerHandle(HT, StringHash("英雄获得物品"), GetItemTypeId(GetManipulatedItem()))
                    if trg != null and IsTriggerEnabled(trg) then
                        index ++
                        u_from[index] = GetTriggerUnit()
                        u_to[index] = u_from[index]
                        if TriggerEvaluate(trg) then
                            TriggerExecute(trg)
                        endif
                        u_from[index] = null
                        u_to[index] = null
                        index --
                    endif
                    trg = null
                } \
            ))
            trg = null
        }

        /*
        物品丢弃
        */

        static void ItemDrop(trigger trg, int iid){
debug@      if LoadTriggerHandle(HT, StringHash("英雄丢弃物品"), iid) != null then
debug@          BJDebugMsg("<错误>重复注册英雄丢弃物品事件:" + I2S(iid))
debug@      endif
            SaveTriggerHandle(HT, StringHash("英雄丢弃物品"), iid, trg)
        }

        static void initItemDrop(){
            trigger trg = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DROP_ITEM)
            TriggerAddCondition(trg, Condition( \
                lambda void(){
                    if not IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
                        return
                    endif
                    trigger trg = LoadTriggerHandle(HT, StringHash("英雄丢弃物品"), GetItemTypeId(GetManipulatedItem()))
                    if trg != null and IsTriggerEnabled(trg) then
                        index ++
                        u_from[index] = GetTriggerUnit()
                        u_to[index] = u_from[index]
                        if TriggerEvaluate(trg) then
                            TriggerExecute(trg)
                        endif
                        u_from[index] = null
                        u_to[index] = null
                        index --
                    endif
                    trg = null
                } \
            ))
            trg = null
        }

        static void ItemPickDrop(trigger trg, int flag, int iid){
            if flag == 0 then
                ItemPick(trg, iid)
            else
                ItemDrop(trg, iid)
            endif
        }

        /*
        英雄复活
        */
        static int HeroRevive_skills[]
        static trigger HeroRevive_trgs[]
        static int HeroRevive_skills_top = 0
        static bool HeroRevive_need_clear = false

        static void HeroRevive(trigger trg, int sid){
            HeroRevive_skills_top ++
            HeroRevive_skills[HeroRevive_skills_top] = sid
            HeroRevive_trgs[HeroRevive_skills_top] = trg

            //记录
            SaveBoolean(HT, GetHandleId(trg), StringHash("英雄复活事件"), true)
        }

        static bool ReviveHero_Hook(unit u, real x, real y, bool b){
            if ReviveHero(u, x, y, b) then
                int i = 1
                index ++
    release@    if HeroRevive_need_clear and index == 0 then
    debug@      if HeroRevive_need_clear then
    debug@          if index != 0 then
    debug@              BJDebugMsg("<清理复活事件>被跳过")
    debug@          else
                    HeroRevive_need_clear = false
                    int x = 0
                    loop
                        exitwhen i > HeroRevive_skills_top
                        if HeroRevive_trgs[i] == null then
                            x ++
                        elseif x != 0 then
                            HeroRevive_trgs[i - x] = HeroRevive_trgs[i]
                            HeroRevive_skills[i - x] = HeroRevive_skills[i]
                        endif
                        i ++
                    endloop
                    HeroRevive_skills_top -= x
                    i = 1
    debug@          endif
                endif

                event_skip[index] = false
                loop
                    exitwhen i > HeroRevive_skills_top or event_skip[index]
                    if (HeroRevive_skills[i] == 0 or GetUnitAbilityLevel(u, HeroRevive_skills[i]) != 0) and IsTriggerEnabled(HeroRevive_trgs[i]) then
                        u_from[index] = u
                        u_to[index] = u
                        if TriggerEvaluate(HeroRevive_trgs[i]) then
                            TriggerExecute(HeroRevive_trgs[i])
                        endif
                    endif
                    i ++
                endloop
                u_from[index] = null
                u_to[index] = null
                index --
                return true
            endif
            return false
        }

        static bool ReviveHeroLoc_Hook(unit u, location loc, bool b){
            return ReviveHero_Hook(u, GetLocationX(loc), GetLocationY(loc), b)
        }

        #define ReviveHero(u, x, y, b) Event.ReviveHero_Hook(u, x, y, b)
        #define ReviveHeroLoc(u, loc, b) Event.ReviveHeroLoc_Hook(u, loc, b)

        static void HeroReviveEventDestroy(trigger trg, int h){
            if LoadBoolean(HT, h, StringHash("英雄复活事件")) then
                int i = 1
                loop
                    exitwhen i > HeroRevive_skills_top
                    if HeroRevive_trgs[i] == trg then
                        HeroRevive_trgs[i] = null
                        i = HeroRevive_skills_top
                        HeroRevive_need_clear = true
                    endif
                    i ++
                endloop
            endif
        }

        /*
        过程剔除事件
        */
        static void ProcessCovered(trigger trg, int key){
            if process.hashindex[key] == 0 then
                return
            endif
            process.trg[key] = trg
        }

        /*
        技能进度条结束事件
        */
        static void SkillBarEnd(trigger trg, unit bar, int flag){
            if flag == 0 then
                SaveTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能成功"), trg)
            elseif flag == 1 then
                SaveTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能失败"), trg)
            endif
        }

        /*
        英雄注册事件
        */
        static int hero_ids[]
        static trigger hero_trgs[]
        static int hero_ids_top = 0
        static trigger Trg = null

        static void HeroInit(trigger trg, int hid){
            hero_ids_top ++
            hero_ids[hero_ids_top] = hid
            hero_trgs[hero_ids_top] = trg
        }

        static void HeroInit_Start(unit hero){
            if LoadBoolean(YDHT, GetHandleId(hero), StringHash("英雄已经被注册过")) then
                return
            endif
            
            SaveBoolean(YDHT, GetHandleId(hero), StringHash("英雄已经被注册过"), true)
            int hid = GetUnitTypeId(hero)
            int i = 1
            index ++
            u_from[index] = hero
            u_to[index] = hero
            event_skip[index] = false
            loop
                exitwhen i > hero_ids_top or event_skip[index]
                if (hid == hero_ids[i] or hero_ids[i] == 0) and hero_trgs[i] != null and IsTriggerEnabled(hero_trgs[i]) and TriggerEvaluate(hero_trgs[i]) then
                    TriggerExecute(hero_trgs[i])
                endif
                i ++
            endloop
            u_from[index] = null
            u_to[index] = null
            index --
        }
        
        /*
        发动暴击事件
        */
        static void Crit(trigger trg){
            int count = LoadInteger(YDHT, Unit.last_CritAddedUnitHandle, Unit.last_CritAddedCount)
            SaveTriggerHandle(YDHT, Unit.last_CritAddedUnitHandle, Unit.last_CritAddedTriggerHandle + count, trg)
        }

        //自定义事件

        __USER_EVENT__

        <?
            update('war3map.j', '自定义事件',
                function(content)
                    local event_names   = {}
                    local code  = [[
                        static trigger user_%hash%_trgs[]
                        static int user_%hash%_top = 0
                        static int user_%hash%_lock = -1
                        static bool user_%hash%_need_clear = false
                        static string user_%hash%_name = "%name%"

                        static void user_%hash%_Init(trigger trg){
                            user_%hash%_top ++
                            user_%hash%_trgs[user_%hash%_top] = trg

                            int h       = GetHandleId(trg)
                            int count   = LoadInteger(HT, h, StringHash("自定义事件数量")) + 1
                            SaveInteger(HT, h, StringHash("自定义事件数量"), count)
                            SaveStr(HT, h, StringHash("自定义事件名") + count, "s__Event_user_%hash%_Destroy")
                        }

                        static void user_%hash%_Start(){
                            int i = 1
                            index ++
                            user_%hash%_lock ++
                release@    if user_%hash%_need_clear and user_%hash%_lock == 0 then
                debug@      if user_%hash%_need_clear then
                debug@          if user_%hash%_lock != 0 then
                debug@              BJDebugMsg("<%name%事件>跳过")
                debug@          else
                debug@          BJDebugMsg("<%name%事件>清理")
                                user_%hash%_need_clear = false
                                int x = 0
                                loop
                                    exitwhen i > user_%hash%_top
                                    if user_%hash%_trgs[i] == null then
                                        x ++
                                    elseif x != 0 then
                                        user_%hash%_trgs[i - x] = user_%hash%_trgs[i]
                                    endif
                                    i ++
                                endloop
                                user_%hash%_top -= x
                                i = 1
                debug@          endif
                            endif
                            SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "%name%")
                            event_skip[index] = false
                            loop
                                exitwhen i > user_%hash%_top or event_skip[index]
                                if IsTriggerEnabled(user_%hash%_trgs[i]) and TriggerEvaluate(user_%hash%_trgs[i]) then
                                    TriggerExecute(user_%hash%_trgs[i])
                                endif
                                i ++
                            endloop
                            SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "")
                            user_%hash%_lock --
                            index --
                        }

                        static void user_%hash%_Destroy(){
                            int i = 1
                            loop
                                exitwhen i > user_%hash%_top
                                if user_%hash%_trgs[i] == Trg then
                debug@              BJDebugMsg("<%name%事件>移除")
                                    user_%hash%_trgs[i] = null
                                    i = user_%hash%_top
                                    user_%hash%_need_clear = true
                                endif
                                i ++
                            endloop
                        }
                    ]]

                    content = content:gsub('Event%.UserEventStart%(%s-(%S-)%s-%)',
                        function(name)
                            if not event_names[name] then
                                table.insert(event_names, name)
                                event_names[name]   = {
                                    hash    = string_hash(name),
                                    name    = name,
                                }
                            end

                            return ('Event.user_%s_Start()'):format(string_hash(name))
                        end
                    )

                    content = content:gsub('Event%.UserEventInit%(%s-(%S-)%s-,%s-(%S-)%s-%)',
                        function(trg, name)
                            if not event_names[name] then
                                table.insert(event_names, name)
                                event_names[name]   = {
                                    hash    = string_hash(name),
                                    name    = name,
                                }
                            end

                            return ('Event.user_%s_Init(%s)'):format(string_hash(name), trg)
                        end
                    )

                    content = content:gsub('__USER_EVENT__',
                        function()
                            local texts = {}
                            for _, t in ipairs(event_names) do
                                local text = code:gsub('%%(.-)%%',
                                    function(k)
                                        return event_names[t][k]
                                    end
                                )
                                table.insert(texts, text)
                            end
                            return table.concat(texts, '\n\n')
                        end
                    )

                    return content
                end
            )
        ?>

        //删除触发器的hook
        static void DestroyTrigger_Hook(trigger trg){
            int h = GetHandleId(trg)

            DamageEventDestroy(trg, h)

            SkillCoolEventDestroy(trg, h)

            HeroReviveEventDestroy(trg, h)

            int i       = 1
            int count   = LoadInteger(HT, h, StringHash("自定义事件数量"))
            Trg = trg
            loop
                exitwhen i > count
                    ExecuteFunc(LoadStr(HT, h, StringHash("自定义事件名") + count))
                i ++
            endloop

            FlushChildHashtable(HT, h)
            DestroyTrigger(trg)
        }
        #define DestroyTrigger(trg) Event.DestroyTrigger_Hook(trg)
        

        //任意单位被创建(包含预设单位,不包含蝗虫)
        static void AnyUnitInit(unit u){
            SaveUnitHandle(YDHT, StringHash("事件"), StringHash("来源"), u)
            SaveUnitHandle(YDHT, StringHash("事件"), StringHash("目标"), u)
            Event.UserEventStart(任意单位被创建)
        }

    endstruct

    private void Init(){
        Event.initSkillEvent()
        Event.initDamageEvent()
        Event.initItemPick()
        Event.initItemDrop()
        Event.initGetSkill()
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library mathLibrary initializer Init needs baseLibrary

    struct math
        /*
        点是否在矩形区域内(起点,角度,长度,宽度,判定点)
        自动清除2个点
        */
        static bool isPointInRect(location A, real a, real l, real w, location B, integer i){
            real Ax=GetLocationX(A)
            real Ay=GetLocationY(A)
            real Bx=GetLocationX(B)
            real By=GetLocationY(B)
            real dx=Bx-Ax
            real dy=By-Ay
            real d=SquareRoot(dx*dx+dy*dy)
            real a2=bj_RADTODEG*Atan2(dy,dx)
            real x=GetLocationX(A)+d*Cos((a2-a)*bj_DEGTORAD)
            real y=GetLocationY(A)+d*Sin((a2-a)*bj_DEGTORAD)
            if i == 1
                RemoveLocation(A)
                RemoveLocation(B)
            elseif i == 2
                RemoveLocation(A)
            elseif i == 3
                RemoveLocation(B)
            endif
            return x>Ax and x<Ax+l and y>Ay-0.5*w and y<Ay+0.5*w
        }


        /*
        令(点)向(方向)移动(距离),(检查地图边界)
        */
        static void MoveLocationAngle(location loc,real a,real r ,bool b){
            if b
                MoveLocation(loc,YDWECoordinateX((GetLocationX(loc)+(r*Cos(bj_DEGTORAD*a)))),YDWECoordinateY((GetLocationY(loc)+(r*Sin(bj_DEGTORAD*a)))))
            else
                MoveLocation(loc,GetLocationX(loc)+(r*Cos(bj_DEGTORAD*a)),GetLocationY(loc)+(r*Sin(bj_DEGTORAD*a)))
            endif
        }

        /*
        极坐标
        自动清除引用点
        */
        static location PolarProjectionMU(location source, real dist, real angle){
            local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
            local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
            call RemoveLocation(source)
            return Location(x, y)
        }

        /*
        单位到点的距离/角度
        */
        static real U2L(unit u,location p,int i,bool b){
            real rs
            if i == 0
                real x = GetUnitX(u)-GetLocationX(p)
                real y = GetUnitY(u)-GetLocationY(p)
                rs = SquareRoot(x*x+y*y)
            elseif i == 1
                rs = bj_RADTODEG * Atan2(GetLocationY(p) - GetUnitY(u), GetLocationX(p) - GetUnitX(u))
            endif
            if b
                RemoveLocation(p)
            endif
            return rs
        }

        /*
        2点间距离/角度
        */
        static real L2L(location locA, location locB, int i, int j){
            real rs
            if i == 0
                real x = GetLocationX(locA) - GetLocationX(locB)
                real y = GetLocationY(locA) - GetLocationY(locB)
                rs = SquareRoot(x*x+y*y)
            elseif i == 1
                rs = bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))
            endif
            if j == 1
                RemoveLocation(locA)
                RemoveLocation(locB)
            elseif j == 2
                RemoveLocation(locA)
            elseif j == 3
                RemoveLocation(locB)
            endif
            return rs
        }

        /*
        获取2个角度的夹角
        参数可以是任意范围
        返回值范围是0-180
        */
        static real Angle(real r1,real r2){
            real r = r1 - r2
            r -= R2I(r/360.)*360.
            if r > 180.
                return 360.-r
            elseif r < -180
                return 360.+r
            elseif r < 0
                return - r
            endif
            return r
        }

        /*
        点在多边形内部
        只支持凸多边形
        */
        private static real PolygonX[]
        private static real PolygonY[]

        static void SetPolygonLocation(int i,real x,real y){
            PolygonX[i]=x
            PolygonY[i]=y
        }

        static bool InsidePolygon(location p,int a,int b,bool bb){
            int n=b
            int count1 = 0
            int count2 = 0
            real value = 0
            loop
                exitwhen a>b
                value = (GetLocationX(p) - PolygonX[n]) * (PolygonY[a] - PolygonY[n]) - (GetLocationY(p) - PolygonY[n]) * (PolygonX[a] - PolygonX[n])
                if value > 0
                    count1++
                elseif value < 0
                    count2++
                endif
                n=a
                a++
            endloop
            if bb
                RemoveLocation(p)
            endif
            return (0 == count1 or 0 == count2)
        }

    endstruct

    private void Init(){
    }

endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library stringLibrary initializer Init needs baseLibrary

    struct String
        private static string char2AllString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

        static string char2(int n){
            if n > 0 and n < 27
                return SubString(char2AllString, n - 1, n)
            endif
            return ""
        }

        static int byte2(string s){
            int i = 0
            loop
                exitwhen i > 26
                if StringCase(s, true) == SubString(char2AllString, i, i + 1) then
                    return i + 1
                endif
                i ++
            endloop
            if i > 9 then
                i = 9
            endif
            return 0
        }

        static string Str[]
        static int StrCount

        static string GetStr(int i){
            if i > .StrCount then
                return ""
            endif
            return .Str[i]
        }

        static int Split(string sss, string sp){
            integer count = 0
            integer i = 0
            integer j = 0
            string s = ""
            int length = StringLength(sss)
            int lengthp = StringLength(sp)
            .Str[0] = sss
            if sss == "" then
                return 0
            endif
            loop
                s = SubString(sss, i, i + lengthp)
                exitwhen s == "" or s == null or i > length
                if s == sp then
                    count = count + 1
                    .Str[count] = SubString(sss, j, i)
                    j = i + lengthp
                    i = j
                endif
                i = i + 1
            endloop
            count = count + 1
            .Str[count] = SubString(sss, j, i)
            .StrCount=count
            return count
        }

        static string ConvertStringExt(string s){
			return s
        }
    endstruct

    private void Init(){
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library playerLibrary initializer Init needs baseLibrary, YDWEBase

    struct sPlayer
        static string name[]
        static string base_name[]

        static string GetPlayerName2(player p){
            return name[GetPlayerId(p)]
        }

        static void SetPlayerName2(player p, string n){
            SetPlayerName(p, n)
            name[GetPlayerId(p)] = n
            Lua_hook(p, "fresh_name")
        }

        static string GetPlayerBaseName(player p){
            return base_name[GetPlayerId(p)]
        }
        
        static int gold[]
        static unit buying_unit = null
        
        static void AdjustPlayerStateBJ2(integer delta, player whichPlayer, playerstate whichPlayerState){
            // If the change was positive, apply the difference to the player's
            // gathered resources property as well.
            call AdjustPlayerStateSimpleBJ(whichPlayer, whichPlayerState, delta)
            if (delta > 0) then
                if (whichPlayerState == PLAYER_STATE_RESOURCE_GOLD) then
                    call AdjustPlayerStateSimpleBJ(whichPlayer, PLAYER_STATE_GOLD_GATHERED, delta)
                    gold[GetPlayerId(whichPlayer)] = GetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_GOLD)
                elseif (whichPlayerState == PLAYER_STATE_RESOURCE_LUMBER) then
                    call AdjustPlayerStateSimpleBJ(whichPlayer, PLAYER_STATE_LUMBER_GATHERED, delta)
                endif
            elseif whichPlayerState == PLAYER_STATE_RESOURCE_GOLD
                gold[GetPlayerId(whichPlayer)] = GetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_GOLD)
            endif
        }
        
        static void SetPlayerStateBJ2(player whichPlayer, playerstate whichPlayerState, integer value){
            local integer oldValue = GetPlayerState(whichPlayer, whichPlayerState)
            call AdjustPlayerStateBJ2(value - oldValue, whichPlayer, whichPlayerState)
        }
        
        static void AddGold(int g){
            int id = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
            gold[id] = GetPlayerState(Player(id), PLAYER_STATE_RESOURCE_GOLD) + g
        }
        
        #define AdjustPlayerStateBJ(i, p, ps) sPlayer.AdjustPlayerStateBJ2(i, p, ps)
        #define SetPlayerStateBJ(p, ps, i) sPlayer.SetPlayerStateBJ2(p, ps, i)
        
        static void FindTrueBuyer(bool find){
            if LoadBoolean(YDHT, StringHash("游戏模式"), StringHash("防守模式")) then
                buying_unit = GetBuyingUnit()
                return
            endif
            buying_unit = null
            
            if find then
                player p = null
                //循环遍历玩家的钱
                int i = 0
                loop
                    exitwhen i > 9
                    if gold[i] != GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD) then
                        
                        //认定真实购买者是该玩家
                        if GetOwningPlayer(GetBuyingUnit()) == Player(i) then
                            buying_unit = GetBuyingUnit()
                        elseif UnitAlive(udg_player[i + 1]) and YDWEDistanceBetweenUnits(udg_player[i + 1], GetSellingUnit()) < 1500 then
                            buying_unit = udg_player[i + 1]
                        elseif UnitAlive(udg_Pet[i + 1]) and YDWEDistanceBetweenUnits(udg_Pet[i + 1], GetSellingUnit()) < 1500 then
                            buying_unit = udg_Pet[i + 1]
                        endif
                        
                        p = Player(i)
                        
                        debug@ BJDebugMsg("<物品购买者>" + GetPlayerName(p))
                        
                        exitwhen true
                    endif
                    i ++
                endloop
                
                //如果没有找到购买者,则退钱
                if buying_unit == null then
                    //2个眼不退,给当前购买者
                    if GetItemTypeId(GetSoldItem()) == 'I03X' or GetItemTypeId(GetSoldItem()) == 'I03W' then
                        buying_unit = GetBuyingUnit()
                    else
                        SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, gold[GetPlayerId(p)])
                        //如果在购买物品事件中移除购买的物品,会导致购买者永久获得该物品的属性
                        //RemoveItem(GetSoldItem())
                        
                        //标记该物品
                        SaveBoolean(YDHT, GetHandleId(GetSoldItem()), StringHash("准备移除该物品"), true)
                        p = null
                        return
                    endif
                endif
                
                gold[i] = GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD)
                p = null
            endif
        }
        
        //在玩家获得物品事件中移除被标记的物品
        static void CheckRemoveItem(){
            item it = GetManipulatedItem()
            int h   = GetHandleId(it)
            
            if LoadBoolean(YDHT, h, StringHash("准备移除该物品")) then
                RemoveSavedBoolean(YDHT, h, StringHash("准备移除该物品"))
                RemoveItem(it)
            endif
            
            it = null
        }
        
        static unit GetBuyingUnit2(){
            return buying_unit
        }
        
        #define GetBuyingUnit() sPlayer.GetBuyingUnit2()
        
        static void FreshPlayerGold(){
            TimerStart(CreateTimer(), 0, false,\
                lambda void(){
                    DestroyTimer(GetExpiredTimer())
                    int i = 0
                    loop
                        exitwhen i > 9
                        gold[i] = GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD)
                        i ++
                    endloop
                }\
            )
        }
        
        static void FreshPlayerGoldImm(){
            int i = 0
            loop
                exitwhen i > 9
                gold[i] = GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD)
                i ++
            endloop
        }

    endstruct

    private void Init(){
        trigger trg
    
        int i = 0
        loop
            exitwhen i > 11
            sPlayer.name[i] = GetPlayerName(Player(i))
            sPlayer.base_name[i] = sPlayer.name[i]
            Lua_hook(Player(i), "fresh_name")
            i ++
        endloop
        
        //卖出物品
        trg = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_PAWN_ITEM)
        TriggerAddCondition(trg, Condition(function sPlayer.FreshPlayerGold))
        
        //购买单位
        trg = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SELL)
        TriggerAddCondition(trg, Condition(function sPlayer.FreshPlayerGoldImm))
        
        //获得物品
        trg = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_PICKUP_ITEM)
        TriggerAddCondition(trg, Condition(function sPlayer.CheckRemoveItem))
        
        trg = null
    }

    #define GetPlayerName(p) sPlayer.GetPlayerName2(p)
    #define SetPlayerName(p, s) sPlayer.SetPlayerName2(p, s)

endlibrary
########
########
//TESH.scrollpos=819
//TESH.alwaysfold=0
library bakaLibrary initializer Init needs baseLibrary

    //反全图
    struct maphack
        static bool safe_mode = true //安全模式

        static unit heroes[] //英雄
        static int heroCount = 0 //英雄计数
        static int heroState[] //英雄可见度状态 0=未知 1=可见 2=不可见
        static real heroHeight[] //英雄高度
        static image heroShadow[] //英雄阴影

        //注册英雄
        static void InitHero(unit hero){
            int i = 1
            loop
                exitwhen GetUnitTypeId(heroes[i]) == 0
                if heroes[i] == hero
                    return
                endif
                i ++
            endloop

            heroes[i] = hero
            heroState[i] = 0
            heroHeight[i] = 0
            heroShadow[i] = baka.Image

            if i > heroCount then
                heroCount = i
            elseif GetUnitTypeId(heroes[heroCount]) == 0 then
                heroCount --
            endif

            UnitAddAbility(hero, 'Arav')
            UnitRemoveAbility(hero, 'Arav')
            debug@ BJDebugMsg("<FMH>添加[" + GetUnitName(hero) + "] 位置[" + I2S(i) + "] 计数:" + I2S(heroCount))

            //添加BUG图标,看到就会崩,防看技能
            if safe_mode or (not IsUnitEnemy(hero, sys.selfp)) or IsPlayerObserver(sys.selfp) then
                UnitAddAbility(hero, 'A0QU')
            else
                UnitAddAbility(hero, 'A9QV')
            endif
            UnitMakeAbilityPermanent(hero, true, 'A0QU')
            UnitMakeAbilityPermanent(hero, true, 'A9QV')
        }

        //偶尔迁移压缩一下数组
        static void zip(){
            int i = 1
            loop
                exitwhen i > heroCount
                if GetUnitTypeId(heroes[i]) == 0 then
                    int j = heroCount
                    loop
                        exitwhen j <= i
                        if GetUnitTypeId(heroes[j]) != 0 then
                            heroes[i] = heroes[j]
                            heroState[i] = heroState[j]
                            heroHeight[i] = heroHeight[j]
                            heroShadow[i] = heroShadow[j]
                            heroes[j] = null
                            debug@ BJDebugMsg("<FMH>移动[" + GetUnitName(heroes[i]) + "] 新的位置[" + I2S(i) + "] 之前的位置[" + I2S(j) + "]")
                            j = 0
                        endif
                        j --
                    endloop
                    heroCount --
                endif
                i ++
            endloop
        }

        //周期检测
        static int check_start_index = 1

        static void TimerFunc(){
            int i = check_start_index
            loop
                exitwhen i > heroCount
                    if IsUnitVisible(heroes[i], sys.selfp) then //单位是否对本地可见
                        //如果可见
                        if heroState[i] != 1 then
                            heroState[i] = 1
                            UnitSetUsesAltIcon(heroes[i], false) //关闭标志,显示英雄图标
                            SetUnitFlyHeight(heroes[i], heroHeight[i], 0) //设置高度为实际高度
                            SetImageColor(heroShadow[i], 255, 255, 255, 255) //显示阴影图像
                        endif
                    elseif GetUnitTypeId(heroes[i]) != 0 then
                        //如果不可见
                        if heroState[i] != 2 then
                            heroState[i] = 2
                        endif
                        UnitSetUsesAltIcon(heroes[i], true) //打开标志,小地图上不显示英雄图标
                        SetUnitFlyHeight(heroes[i], 10000, 0) //让英雄飞上天
                        SetImageColor(heroShadow[i], 255, 255, 255, 0) //隐藏阴影图像
                    endif
                i ++
            endloop
        }

        //设置高度
        static void SetHeight(unit u, real h, real r){
            if IsUnitType(u, UNIT_TYPE_GIANT) then
                return
            endif

            if IsUnitType(u, UNIT_TYPE_HERO) then
                int i = 1
                loop
                    exitwhen i > heroCount
                    if heroes[i] == u then
                        heroHeight[i] = h
                        if heroState[i] != 2 then
                            SetUnitFlyHeight(u, h, 0)
                        endif
                        return
                    endif
                    i ++
                endloop
            endif

            SetUnitFlyHeight(u, h, r)
        }

        //获取高度
        static real GetHeight(unit u){
            if IsUnitType(u, UNIT_TYPE_HERO) then
                int i = 1
                loop
                    exitwhen i > heroCount
                    if heroes[i] == u then
                        return heroHeight[i]
                    endif
                    i ++
                endloop
            endif

            return GetUnitFlyHeight(u)
        }

        //正义巡视者系统
        static unit visitors[]
        static int visitorsCount = 0

        static timer check_timer = CreateTimer()
        static unit check_unit
        static fogmodifier fog[]

        static int check_id = 0

        //检测是否是因为BUG模型而崩溃
        static void check_MH_crash(){
            local player p = GetTriggerPlayer()
            local integer i = baka.spid[GetPlayerId(p)]
            if GetStoredInteger(sys.GC, "MH1", I2S(i)) > GetStoredInteger(sys.GC, "MH2", I2S(i)) then
                if sys.isIn11() then
                    Lua_hook(p, "log FMH检测数据有异常")
                    //Lua_hook(sys.selfp, "maid_chat 主人主人,刚刚【" + GetPlayerName(p) + "】开图被我发现了")
                    //Lua_hook(sys.selfp, "maid_chat 我果断把他踢掉了,快夸奖我一下吧~")
                else
                    //BJDebugMsg(GetPlayerName(p) + "|cffff1111因为使用全图作弊工具被T出游戏啦!|r")
                endif
            endif
            p = null
        }

        static void timerFunc3(){
            SetUnitPosition(check_unit, -4000, 8000)

            ShowUnit(check_unit, false)

            RemoveUnit(check_unit)

            int i = 0
            loop
                exitwhen i > 9
                if fog[i] != null then
                    DestroyFogModifier(fog[i])
                    fog[i] = null
                    //debug@ Lua_hook(sys.selfp, "print p4:i=" + I2S(i))
                endif
                i ++
            endloop

            //发送一个数据
            TimerStart(check_timer, 0.2, false, \
                lambda void (){
                    StoreInteger(sys.GC, "MH2", I2S(sys.self), R2I(sys.getTime()))
                    SyncStoredInteger(sys.GC, "MH2", I2S(sys.self))
                }\
            )
        }

        static void timerFunc2(unit hero){
            real x = GetUnitX(hero)
            real y = GetUnitY(hero)
            bool flag = false

            int i = 0
            loop
                exitwhen i > 9
                player p = Player(i)

                if /*
                    */not IsVisibleToPlayer(x, y, p) and /*
                    */not IsVisibleToPlayer(x + 256, y, p) and /*
                    */not IsVisibleToPlayer(x - 256, y, p) and /*
                    */not IsVisibleToPlayer(x, y + 256, p) and /*
                    */not IsVisibleToPlayer(x, y - 256, p) /*
                */then

                    fog[i] = CreateFogModifierRadius(p, FOG_OF_WAR_FOGGED, x, y, 128, true, true)
                    FogModifierStart(fog[i])
                    if sys.IsReplay != 1 and sys.selfp == p then
                        flag = true
                    endif
                    //debug@ Lua_hook(sys.selfp, "print p3:i=" + I2S(i))
                else
                    //debug@ Lua_hook(sys.selfp, "print p5:i=" + I2S(i))
                endif

                p = null
                i ++
            endloop


            check_unit = CreateUnit(GetOwningPlayer(hero), 'e98U', -4000, 8000, 0)

            //debug@ BJDebugMsg(R2S(GetUnitX(check_unit)))

            if flag then
                SetUnitFlyHeight(check_unit, 0, 0)
            else
                SetUnitFlyHeight(check_unit, 1000000, 0)
            endif

            if (x < -500 or x > 700) and (y < -1000 and y > 100) then
                SetUnitPosition(check_unit, x, y)
            endif

            UnitRemoveAbility(check_unit, 'Amov')

            //准备销毁BUG模型与视野修正
            TimerStart(check_timer, 0.05, false, function maphack.timerFunc3)
        }



        static void timerFunc(){
            //循环检查
            check_id ++
            if check_id > 9 then
                check_id = 0
            endif

            TimerStart(GetExpiredTimer(), GetRandomInt(3, 5) * 0.7, false, function maphack.timerFunc)

            if ModuloInteger(check_id, 3) == 0 then
                int i = 0
                loop
                    exitwhen i > visitorsCount

                    if GetRandomInt(1, 3) == 2 and GetUnitCurrentOrder(visitors[i]) == 0 then
                        player pl = GetOwningPlayer(visitors[i])

                        real x = GetRandomInt(-100, 100) * 70
                        real y = GetRandomInt(-100, 100) * 70

                        SetUnitX(visitors[i], x)
                        SetUnitY(visitors[i], y)

                        UnitSetUsesAltIcon(visitors[i], true) //打开标志,小地图上不显示英雄图标
                        SetUnitFlyHeight(visitors[i], 1000000, 0) //让英雄飞上天

                        x = GetRandomInt(-100, 100) * 70
                        y = GetRandomInt(-100, 100) * 70

                        IssuePointOrder(visitors[i], "move", x, y)
                        UnitSetUsesAltIcon(visitors[i], true)
                    endif
                    //DestroyEffect(AddSpecialEffectTarget("Tsukiko.mdl", visitors[i], "origin"))
                    i ++
                endloop
            endif

            release@ return

            if safe_mode then
                return
            endif

            //在视野外的英雄头上创建BUG模型;对非该玩家进行特例;对录像进行特例
            //debug@ Lua_hook(sys.selfp, "print p1:check_id=" + I2S(check_id))
            unit hero = udg_player[check_id + 1]

            if GetUnitTypeId(hero) != 0 then
                timerFunc2(hero)

                //发送一个数据
                StoreInteger(sys.GC, "MH1", I2S(sys.self), R2I(sys.getTime()))
                SyncStoredInteger(sys.GC, "MH1", I2S(sys.self))
            endif

            hero = null

        }

        //检查录像(录像模式关闭FMH)
        static void WaitToCheckReplay(){
            if sys.IsReplay == -1 and sys.getTime() < 30 then
                return
            endif

            if sys.getTime() > 25 then
                BJDebugMsg("<录像检查>超时!请汇报BUG(请附带当前玩家信息/是否有玩家退出)")
            endif

            if IsPlayerObserver(sys.selfp) or sys.IsReplay == 1 then
                check_start_index = 10000
            endif

            TimerStart(GetExpiredTimer(), 0.05, true, function maphack.TimerFunc) //启动计时器,周期0.05秒检查视野
        }

        static void InitS(){
            TimerStart(CreateTimer(), 0.5, true, function maphack.WaitToCheckReplay)

            SetAltMinimapIcon("null_16_16.blp") //设置小地图中立标志为透明图标
        }

        static void AfterSP(){
            //创建巡视者
            int i = 0
            loop
                exitwhen i > 9
                player p = Player(i)
                int j = 0
                loop
                    exitwhen j > 4
                    real x = GetRandomInt(-100, 100) * 70
                    real y = GetRandomInt(-100, 100) * 70
                    if IsPlayerAlly(p, sys.selfp) or sys.IsReplay == 1 or GetPlayerTeam(p) == -1 then
                        visitors[visitorsCount] = CreateUnit(p, 'H00H', x, y, 0)
                    else
                        visitors[visitorsCount] = CreateUnit(p, 'H90G', x, y, 0)
                    endif
                    UnitSetUsesAltIcon(visitors[visitorsCount], true) //打开标志,小地图上不显示英雄图标
                    SetUnitFlyHeight(visitors[visitorsCount], 10000, 0) //让英雄飞上天
                    SetHeroLevel(visitors[visitorsCount], 30, false) //设置英雄为满级以免分经验
                    visitorsCount ++
                    j ++
                endloop
                i ++
            endloop
            TimerStart(CreateTimer(), 5, false, function maphack.timerFunc)
            TimerStart(CreateTimer(), GetRandomInt(60, 120), true, function maphack.zip)
            /*
            //修正视野外杀野看不到金钱获取的BUG
            trigger trg = CreateTrigger()
            Event.AnyUnitDamage(trg, 2, 0)
            TriggerAddCondition(trg, Condition( \
                lambda void(){
                    if GetOwningPlayer(GetTriggerUnit()) == Player(12) and GetOwningPlayer(GetEventDamageSource()) == sys.selfp and not IsUnitVisible(GetTriggerUnit(), sys.selfp) then
                        SetUnitFlyHeight(GetTriggerUnit(), 0, 0)
                    endif
                } \
            ))
            */
        }

        #define SetUnitFlyHeightBJ maphack.SetHeight
        #define SetUnitFlyHeight maphack.SetHeight
        #define GetUnitFlyHeight maphack.GetHeight

        static group GetUnitsInRangeOfLocAllSub(real r, location l){
            return YDWEGetUnitsInRangeOfLocMatchingNull(r, l, Condition( \
                lambda bool(){
                    return not IsUnitType(GetFilterUnit(), UNIT_TYPE_TAUREN)
                } \
            ))
        }

        //选取单位不选中特殊单位
        #define YDWEGetUnitsInRangeOfLocAllNull(r, l) maphack.GetUnitsInRangeOfLocAllSub(r, l)
    endstruct



    //专用库
    struct baka
        /*
        (单位) 在吃到好符的几率为 (几率) 的情况下吃了个 (好/坏) 符
        */
        static void lucky(unit u, real r, bool b){
            int i = GetPlayerId(GetOwningPlayer(u))
            int x = Get(i, "L0") + 1
            Set(i, "L0", x)
            int y = Get(i, "L1")
            if b
                y += R2I((100-r)*100)
            else
                y -= R2I(r*100)
            endif
            Set(i, "L1", y)
            int z = Get(i, "幸运")
            z = y/x
            Set(i, "幸运", z)
            Save()
        }

        /*
        OB可以共享玩家(可以看到玩家的技能)
        */
        static void OB(){
            int i = 0
            loop
                exitwhen i > 9
                SetPlayerAlliance(Player(i), Player(10), ALLIANCE_SHARED_CONTROL, true)
                SetPlayerAlliance(Player(i), Player(11), ALLIANCE_SHARED_CONTROL, true)
                i++
            endloop
        }

        /*
        洗牌模式用
        */

        static player spplayer[]
        static int spid[]

        static void InitSP(){
            int i = 0
            loop
                exitwhen i > 15
                spplayer[i] = Player(i)
                spid[i] = i
                i++
            endloop
        }

        static player SPlayer(int i){
            return spplayer[i]
        }

        static int SGetPlayerId(player p){
            return spid[GetPlayerId(p)]
        }

        static group g[]

        //重置变量记录
        static void UnitDefine(){
            unit u1[]
            unit u2[]
            int i = 0
            loop
                exitwhen i > 9
                u1[i] = udg_SmD[i + 1] //生命灯
                u2[i] = udg_wupinqiu[i + 1] //物品球
                i ++
            endloop

            i = 0
            loop
                exitwhen i > 9
                udg_SmD[spid[i] + 1] = u1[i]
                udg_wupinqiu[spid[i] + 1] = u2[i]
                i ++
            endloop
        }

        /*洗牌函数说明
        玩家1-10随机重新组队,并重置所有单位颜色与玩家结盟关系,交换生命灯的位置
        */
        static void Sp(){
            int startLocIndex[] //玩家游戏开始位置的索引
            int i = 0
            int oids[]
            loop
                exitwhen i > 9
                oids[i] = i
                startLocIndex[i] = GetPlayerStartLocation(Player(i))
                //将该玩家的所有单位记录下来准备进行交换
                g[i] = CreateGroup()
                GroupEnumUnitsOfPlayer(g[i], Player(i), null)
                i++
            endloop
            int nids[]
            i = 0
            loop
                exitwhen i > 9
                int index = GetRandomInt(0, 9-i) //随机提取出一个玩家
                int id = oids[index] //找到这个玩家的ID
                nids[i] = id //提取出的玩家放到新的玩家序列中
                int j = index
                loop //将后面的玩家序列往前移动一个位置
                    exitwhen j > 9
                    oids[j] = oids[j+1]
                    j++
                endloop
                i++
            endloop
            i = 0
            loop
                exitwhen i > 9
                spplayer[i] = Player(nids[i])
                spid[nids[i]] = i
                debug@ BJDebugMsg("<洗牌>玩家: " + I2S(nids[i]) + " → 玩家: " + I2S(i))
                SetPlayerStartLocation(spplayer[i], startLocIndex[i])
                SetPlayerColor(spplayer[i], ConvertPlayerColor(i))
                //BJDebugMsg(I2S(nids[i]) + " → " + I2S(i))
                forGroup(u, g[i])
                    SetUnitOwner(u, spplayer[i], true)
                endGroup
                i++
            endloop
            int x = 0
            loop
                exitwhen x > 4
                SetPlayerTeam(spplayer[x], 0)
                int y = 0
                loop
                    exitwhen y > 4
                    SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[y], true)
                    SetPlayerAlliance(spplayer[x], spplayer[y], ALLIANCE_SHARED_VISION, true)
                    SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[y+5], false)
                    SetPlayerAlliance(spplayer[x], spplayer[y+5], ALLIANCE_SHARED_VISION, false)
                    y++
                endloop
                SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[10], true)
                SetPlayerAlliance(spplayer[x], spplayer[10], ALLIANCE_SHARED_VISION, true)
                SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[11], false)
                SetPlayerAlliance(spplayer[x], spplayer[11], ALLIANCE_SHARED_VISION, false)
                SetPlayerAllianceStateAllyBJ(spplayer[10], spplayer[x], true)
                SetPlayerAlliance(spplayer[10], spplayer[x], ALLIANCE_SHARED_VISION, true)
                SetPlayerAlliance(spplayer[10], spplayer[x], ALLIANCE_HELP_REQUEST, false)
                SetPlayerAllianceStateAllyBJ(spplayer[11], spplayer[x], false)
                SetPlayerAlliance(spplayer[11], spplayer[x], ALLIANCE_SHARED_VISION, false)
                SetPlayerAlliance(spplayer[x], spplayer[x], ALLIANCE_HELP_REQUEST, false)
                SetPlayerAlliance(spplayer[x], spplayer[15], ALLIANCE_SHARED_VISION, true)
                SetPlayerAlliance(spplayer[x], spplayer[14], ALLIANCE_SHARED_VISION, false)
                x++
            endloop
            x = 5
            loop
                exitwhen x > 9
                SetPlayerTeam(spplayer[x], 1)
                int y = 5
                loop
                    exitwhen y > 9
                    SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[y], true)
                    SetPlayerAlliance(spplayer[x], spplayer[y], ALLIANCE_SHARED_VISION, true)
                    SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[y-5], false)
                    SetPlayerAlliance(spplayer[x], spplayer[y-5], ALLIANCE_SHARED_VISION, false)
                    y++
                endloop
                SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[11], true)
                SetPlayerAlliance(spplayer[x], spplayer[11], ALLIANCE_SHARED_VISION, true)
                SetPlayerAllianceStateAllyBJ(spplayer[x], spplayer[10], false)
                SetPlayerAlliance(spplayer[x], spplayer[10], ALLIANCE_SHARED_VISION, false)
                SetPlayerAllianceStateAllyBJ(spplayer[11], spplayer[x], true)
                SetPlayerAlliance(spplayer[11], spplayer[x], ALLIANCE_SHARED_VISION, true)
                SetPlayerAlliance(spplayer[11], spplayer[x], ALLIANCE_HELP_REQUEST, false)
                SetPlayerAllianceStateAllyBJ(spplayer[10], spplayer[x], false)
                SetPlayerAlliance(spplayer[10], spplayer[x], ALLIANCE_SHARED_VISION, false)
                SetPlayerAlliance(spplayer[x], spplayer[x], ALLIANCE_HELP_REQUEST, false)
                SetPlayerAlliance(spplayer[x], spplayer[15], ALLIANCE_SHARED_VISION, false)
                SetPlayerAlliance(spplayer[x], spplayer[14], ALLIANCE_SHARED_VISION, true)
                x++
            endloop
            OB()
            //sys.self = SGetPlayerId(sys.selfp)
            //UnitDefine()
        }

        <?
            --取消对Player的define,以免影响config函数导致地图无法启动
            update('war3map.j', '取消Player的define',
                function(content)
                    return content:gsub('(function InitCustomPlayerSlots takes nothing returns nothing.+)',
                        function(s)
                            s = s:gsub('baka.SPlayer', 'Player')
                            s = s:gsub('baka.SGetPlayerId', 'GetPlayerId')
                            return s
                        end
                    )
                end
            )
        ?>

        //对player进行define以支持洗牌模式
        #define Player(i) baka.SPlayer(i)
        #define ConvertedPlayer(i) baka.SPlayer(i-1)
        #define GetPlayerId(p) baka.SGetPlayerId(p)
        #define GetConvertedPlayerId(p) (baka.SGetPlayerId(p)+1)

        static string thisVerName = "__MAP_VER_NAME__"
        static int thisVer = 0
        static string thatVerName = ""

        static void oldMapTimerFunc(){
            BJDebugMsg("|cff00ccff当前地图版本并非最新版本,积分已经关闭.检测到的最新版本为 |cffffcc00" + thatVerName + "|r")
        }

        static void banMapTimerFunc(){
            BJDebugMsg("|cff00ccff当前地图版本已经废弃,请更换新版本地图进行游戏|r")
        }

        static int getMapVerInt(string name){
            int i1 = S2I(SubString(name, 0, 1)) * 100
            int i2 = S2I(SubString(name, 2, 3)) * 10
            int i3 = String.byte2(SubString(name, 3, 4))
            return i1 + i2 + i3
        }

        static string getMapVerName(int ver){
            string s1 = I2S(ver / 100)
            string s2 = I2S(ModuloInteger(ver, 100) / 10)
            string s3 = String.char2(ModuloInteger(ver, 10))
            return s1 + "." + s2 + s3
        }

        static void oldMap(int thatVer, bool flag){
            thatVerName = getMapVerName(thatVer)
            if flag then
                TimerStart(CreateTimer(), 1, false, function baka.oldMapTimerFunc)
                TimerStart(CreateTimer(), 300, true, function baka.oldMapTimerFunc)
            else
                TimerStart(CreateTimer(), 1, false, null)
                TimerStart(CreateTimer(), 300, true, null)
            endif
        }
        
        static bool hasPlayed = false

        static bool newMap(){
            //设置当前版本号
            thisVer = getMapVerInt(thisVerName)
            //寻找所有玩家记录的最新版本
            int thatVer = 0
            int banVer = 0
            int x = 0
            loop
                exitwhen x > 11
                int that = Get(x, "V2")
                if that > thatVer
                    thatVer = that
                endif
                int ban = Get(x, "B")
                if ban > banVer
                    banVer = ban
                endif
                //特例,顺便检查是否是录像状态(局数都为0)
                if Get(x, "局数") != 0 then
                    hasPlayed = true
                endif
                x ++
            endloop
            if thatVer > thisVer
                oldMap(thatVer, true) //确认当前玩的地图是旧版本
            else
                oldMap(thatVer, false)
                thatVer = thisVer
            endif
            //更新所有玩家记录的最新版本数据
            x = 0
            loop
                exitwhen x > 11
                if Get(x, "V2") < thatVer then
                    Lua_hook(Player(x), "new_version")
                    release@ Set(x, "V2", thatVer)
                endif
                release@ Set(x, "B", banVer)
                x ++
            endloop
            //根据情况是否废除当前版本地图
            if banVer >= thisVer
                EnableUserUI(false)
                TimerStart(CreateTimer(), 1, false, function baka.banMapTimerFunc)
                TimerStart(CreateTimer(), 60, true, function baka.banMapTimerFunc)
                return false
            endif
            if thatVer > thisVer
                return false
            endif
            return true
        }

        //动态炸弹人类型
        static group CG1 = CreateGroup() //万物可见
        static group CG2 = CreateGroup() //万物不可见
        static group CG3 = CreateGroup() //极寒可见
        static group CG4 = CreateGroup() //极寒不可见

        static unit CU = null

        static void Check1(){
            CU = GetEnumUnit()
            if IsUnitInvisible(CU, Player(11)) or IsUnitInvisible(CU, Player(14)) then
                GroupRemoveUnit(CG1, CU)
                GroupAddUnit(CG2, CU)
                UnitAddType(CU, UNIT_TYPE_SAPPER)
                // BJDebugMsg("万物离开视野:" + GetUnitName(CU))
            else
                UnitRemoveType(CU, UNIT_TYPE_SAPPER)
            endif
        }

        static void Check2(){
            CU = GetEnumUnit()
            if IsUnitVisible(CU, Player(11)) and IsUnitVisible(CU, Player(14)) then
                GroupRemoveUnit(CG2, CU)
                GroupAddUnit(CG1, CU)
                UnitRemoveType(CU, UNIT_TYPE_SAPPER)
                // BJDebugMsg("万物进入视野:" + GetUnitName(CU))
            else
                UnitAddType(CU, UNIT_TYPE_SAPPER)
            endif
        }

        static void Check3(){
            CU = GetEnumUnit()
            if IsUnitInvisible(CU, Player(10)) or IsUnitInvisible(CU, Player(15)) then
                GroupRemoveUnit(CG3, CU)
                GroupAddUnit(CG4, CU)
                UnitAddType(CU, UNIT_TYPE_SAPPER)
                // BJDebugMsg("极寒离开视野:" + GetUnitName(CU))
            else
                UnitRemoveType(CU, UNIT_TYPE_SAPPER)
            endif
        }

        static void Check4(){
            CU = GetEnumUnit()
            if IsUnitVisible(CU, Player(10)) and IsUnitVisible(CU, Player(15)) then
                GroupRemoveUnit(CG4, CU)
                GroupAddUnit(CG3, CU)
                UnitRemoveType(CU, UNIT_TYPE_SAPPER)
                // BJDebugMsg("极寒进入视野:" + GetUnitName(CU))
            else
                UnitAddType(CU, UNIT_TYPE_SAPPER)
            endif
        }

        static void CheckVisible(){
            ForGroup(CG1, function baka.Check1)
            ForGroup(CG2, function baka.Check2)
            ForGroup(CG3, function baka.Check3)
            ForGroup(CG4, function baka.Check4)
        }

        static trigger CheckDeath = CreateTrigger()

        static int CheckCount = 0

        static bool CheckSummon(){
            CU = GetSummonedUnit()
            if IsUnitAlly(CU, Player(10)) then
                GroupAddUnit(CG1, CU)
            else
                GroupAddUnit(CG3, CU)
            endif
            TriggerRegisterUnitEvent(CheckDeath, CU, EVENT_UNIT_DEATH)
            CheckCount ++
            // BJDebugMsg("<视野检查> 单位名称[" + GetUnitName(CU) + "] 计数[" + I2S(CheckCount) + "]")
            return false
        }

        static bool SummonDeath(){
            CU = GetTriggerUnit()
            GroupRemoveUnit(CG1, CU)
            GroupRemoveUnit(CG2, CU)
            GroupRemoveUnit(CG3, CU)
            GroupRemoveUnit(CG4, CU)
            CheckCount --
            // BJDebugMsg("<视野检查> 单位名称[" + GetUnitName(CU) + "] 计数[" + I2S(CheckCount) + "]")
            return false
        }

        //注册英雄
        static void InitHero(unit hero){
            //令英雄可以改变高度
            UnitAddAbility(hero, 'Arav')
            UnitRemoveAbility(hero, 'Arav')
            //添加英雄光晕
            UnitAddAbility(hero, 'A087')
            SetPlayerAbilityAvailable(GetOwningPlayer(hero), 'A087', false)
            UnitMakeAbilityPermanent(hero, true, 'A087')
            UnitMakeAbilityPermanent(hero, true, 'A0R8')
            //maphack.InitHero(hero)
            if IsUnitAlly(hero, Player(10)) then
                GroupAddUnit(CG1, hero)
            else
                GroupAddUnit(CG3, hero)
            endif
            //给Lua的hook
            UnitW##akeUp(hero)
            //发起英雄注册事件
            Event.HeroInit_Start(hero)
        }

        //截取新建单位的阴影图像
        static image Image = null

        static void hookImage(){
            Image = CreateImage("Shadow", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
            DestroyImage(Image)
        }

        //带反全图的创建单位
        static group CreateNUnitsAtLoc2(integer count, integer unitId, player whichPlayer, location loc, real face){
            GroupClear(bj_lastCreatedGroup)
            loop
                count --
                exitwhen count < 0
                hookImage()
                bj_lastCreatedUnit = CreateUnitAtLoc(whichPlayer, unitId, loc, face)
                maphack.InitHero(bj_lastCreatedUnit)
                GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
            endloop
            return bj_lastCreatedGroup
        }

        //游戏开始
        static void AfterSP(){
            maphack.AfterSP()
            Event.UserEventStart(游戏模式选择完毕)
        }

        //闪电效果
        static lightning AddLightningEx2(string name, bool check, real x1, real y1, real z1, real x2, real y2, real z2){
            if check and not IsPlayerObserver(sys.selfp) and not IsVisibleToPlayer(x1, y1, sys.selfp) and not IsVisibleToPlayer(x2, y2, sys.selfp) then
                return AddLightningEx(name, false, 0, 0, 1000000, 0, 0, 1000000)
            else
                return AddLightningEx(name, false, x1, y1, z1, x2, y2, z2)
            endif
        }

        static bool MoveLightningEx2(lightning whichBolt, boolean checkVisibility, real x1, real y1, real z1, real x2, real y2, real z2){
            if checkVisibility and not IsPlayerObserver(sys.selfp) and not IsVisibleToPlayer(x1, y1, sys.selfp) and not IsVisibleToPlayer(x2, y2, sys.selfp) then
                return MoveLightningEx(whichBolt, false, 0, 0, 1000000, 0, 0, 1000000)
            else
                return MoveLightningEx(whichBolt, false, x1, y1, z1, x2, y2, z2)
            endif
        }

        #define AddLightningEx(s, b, x1, y1, z1, x2, y2, z2) baka.AddLightningEx2(s, b, x1, y1, z1, x2, y2, z2)
        #define MoveLightningEx(l, b, x1, y1, z1, x2, y2, z2) baka.MoveLightningEx2(l, b, x1, y1, z1, x2, y2, z2)

        //可破坏物是否是树(通过ID枚举)
        <?
            local all_ids   = table.back {'B002', 'YTfb', 'B003', 'YTpb', 'ATtc', 'BTtc', 'ATtr', 'BTtw', 'ZTg1', 'FTtw', 'B004', 'CTtc', 'YT11', 'BTsc', 'ZTg2', 'CTtr', 'B000', 'LT06', 'LTrc', 'YTpc'}
            local ids       = {}

            for _, id in ipairs(all_ids) do
            if slk.destructable[id].Name:match '树' then
                table.insert(ids, ("id == '%s'"):format(id))
            end
            end

            local push      = table.concat(ids, ' or ')
        ?>

        static bool IsDestructableWood(destructable des){
            int id  = GetDestructableTypeId(des)
            return <?=push?>
        }
    endstruct

    private void Init(){
        baka.InitSP()
        maphack.InitS()

        TimerStart(CreateTimer(), 0.1, true, function baka.CheckVisible)
        //单位被召唤时,加入检测
        trigger trg = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SUMMON)
        TriggerAddCondition(trg, Condition(function baka.CheckSummon))
        //召唤单位死亡时,取出检测
        TriggerAddCondition(baka.CheckDeath, Condition(function baka.SummonDeath))
        //
        trg = null
    }
endlibrary
########
########
//TESH.scrollpos=235
//TESH.alwaysfold=0
library unitLibrary initializer Init needs bakaLibrary

    struct Unit
        /*
        替换单位物品栏中的物品
        注意替换过程中换多次触发单位获得/失去物品事件
        单位处于无法拾取物品的状态时会替换失败
        */
        static void ExchangeItem(unit luu, int ItemID1, int ItemID2, bool b1, bool b2){
            int i1 = 0
            int i2 = 0
            int a1
            int a2
            real a3
            item lii
            item li2
            int playerid
            loop
                exitwhen i1 > 5
                lii = UnitItemInSlot(luu,i1)
                if GetItemTypeId(lii) == ItemID1 then
                    a1 = GetItemUserData(lii)
                    a2 = GetItemCharges(lii)
                    a3 = GetWidgetLife(lii)
                    playerid = GetPlayerId(GetItemPlayer(lii))
                    RemoveItem(lii)
                    loop
                        exitwhen i2 > i1 - 1
                        if UnitItemInSlot(luu, i2) == null then
                            UnitAddItem(luu, CreateItem('I02S', GetUnitX(luu), GetUnitY(luu)))
                        endif
                        i2++
                    endloop
                    li2 = CreateItem(ItemID2,-7220, 7115)
                    UnitAddItem(luu, li2)
                    if b1
                        SetItemUserData( li2, a1 )
                    endif
                    if b2
                        SetItemCharges( li2, a2 )
                    endif
                    SetWidgetLife( li2, a3 )
                    SetItemPlayer(li2,Player(playerid),false)
                    i2 = 0
                    loop
                        exitwhen i2 > i1 - 1
                        lii = UnitItemInSlot(luu, i2)
                        if GetItemTypeId(lii) == 'I02S' then
                            RemoveItem( lii )
                        endif
                        i2++
                    endloop
                endif
                i1++
            endloop
            lii = null
            li2 = null
        }

        /*
        令(单位)向(方向)移动(距离)
        单位移动速度为0则不作动作(否则可能会灵肉分离)
        */
        static bool MoveSuccess = false
        static real lastMoveDis = 0

        static bool Move(unit u,real a,real r){
            if GetUnitDefaultMoveSpeed(u) == 0
                return false
            endif
            
            real x = LoadReal(YDHT, GetHandleId(u), StringHash("移动干涉"))
            lastMoveDis = r + r * x / 100
            SetUnitX(u, YDWECoordinateX((GetUnitX(u) + (lastMoveDis * Cos(bj_DEGTORAD * a)))))
            SetUnitY(u, YDWECoordinateY((GetUnitY(u) + (lastMoveDis * Sin(bj_DEGTORAD * a)))))
            return true
        }

        static bool Move2(unit u,real a,real r, pathingtype t){
            if GetUnitDefaultMoveSpeed(u) == 0
                return false
            endif
            
            real x = LoadReal(YDHT, GetHandleId(u), StringHash("移动干涉"))
            lastMoveDis = r + r * x / 100
            real x0 = GetUnitX(u)
            real y0 = GetUnitY(u)
            real x1 = x0 + (lastMoveDis * Cos(bj_DEGTORAD * a))
            real y1 = y0 + (lastMoveDis * Sin(bj_DEGTORAD * a))
            if not IsTerrainPathable(x1, y1, t) then
                SetUnitX(u, x1)
                SetUnitY(u, y1)
                return true
            elseif not IsTerrainPathable(x1, y0, t) then
                SetUnitX(u, x1)
                SetUnitY(u, y0)
            elseif not IsTerrainPathable(x0, y1, t) then
                SetUnitX(u, x0)
                SetUnitY(u, y1)
            endif
            return false
        }

        define <call Unit.Move> = {set Unit.MoveSuccess = Unit.Mo##ve}
        define <call Unit.Move2> = {set Unit.MoveSuccess = Unit.Mo##ve2}

        /*
        设置单位的XY坐标
        */
        static void SetUnitXY(unit u, real x, real y){
            SetUnitX(u, YDWECoordinateX(x))
            SetUnitY(u, YDWECoordinateY(y))
        }

        static void SetUnitXYOffset(unit u, real x, real y, real a, real r){
            x = x + r * Cos(bj_DEGTORAD * a)
            y = y + r * Sin(bj_DEGTORAD * a)
            SetUnitX(u, YDWECoordinateX(x))
            SetUnitY(u, YDWECoordinateY(y))
        }

        /*
        创建多个单位(点)
        自动清除引用点
        */
        static group CreateNUnitsAtLocMU(integer count, integer unitId, player whichPlayer, location loc, real face){
            call GroupClear(bj_lastCreatedGroup)
            loop
                set count = count - 1
                exitwhen count < 0
                set bj_lastCreatedUnit = CreateUnitAtLoc(whichPlayer, unitId, loc, face)
                call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
            endloop
            call RemoveLocation(loc)
            return bj_lastCreatedGroup
        }

        /*
        创建单位(点)
        自动清除引用点
        */
        static unit CreateUnitAtLocMU(player id, integer unitid, location whichLocation, real face){
            real x = GetLocationX(whichLocation)
            real y = GetLocationY(whichLocation)
            RemoveLocation(whichLocation)
            return CreateUnit(id, unitid, x, y, face)
        }

        /*
        移动单位(点)
        自动清除引用点
        */
        static void SetUnitPositionLocMU(unit u ,location loc){
            SetUnitPositionLoc(u,loc)
            RemoveLocation(loc)
        }

        /*
        选取直线范围内的单位
        */
        static group GetUnitInLineAll(location loc, bool flag, real ang, real len, real dis){
            real x1 = GetLocationX(loc)
            real y1 = GetLocationY(loc)
            if flag then
                RemoveLocation(loc)
            endif
            real x2 = x1 + len * Cos(ang * bj_DEGTORAD)
            real y2 = y1 + len * Sin(ang * bj_DEGTORAD)

            //线段中点
            real x0 = (x1 + x2) / 2
            real y0 = (y1 + y2) / 2

            //直线公式 A*x + B*y + C = 0
            real A = y1 - y2
            real B = x2 - x1
            real C = - A * x1 - B * y1

            //点到线段公式│AXo＋BYo＋C│／√（A^2＋B^2）
            real s = SquareRoot(A * A + B * B)
            if s == 0 then
                s = 1
            endif

            //使用拟合圆进行初步选取
            group g = CreateGroup()
            GroupEnumUnitsInRange(g, x0, y0, len / 2, null)

            //进行逐个精选
            sys.g = CreateGroup()
            loop
                unit u = FirstOfGroup(g)
                exitwhen u == null
                GroupRemoveUnit(g, u)
                //判定距离
                real x = GetUnitX(u)
                real y = GetUnitY(u)
                real d = (A * x + B * y + C) / s
                if d < 0 then
                    d = - d
                endif
                if d < dis then
                    GroupAddUnit(sys.g, u)
                endif
            endloop
            DestroyGroup(g)
            g = null
            return sys.g
        }

        /*
        选取原型范围内的单位(点)
        自动清除引用点
        */
        static group GetUnitsInRangeOfLocMatchingMU(real radius, location whichLocation, boolexpr filter){
            local group g = CreateGroup()
            call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
            call RemoveLocation(whichLocation)
            call DestroyBoolExpr(filter)
            set sys.g = g
            set g = null
            return sys.g
        }

        static group GetUnitsInRangeOfLocAllMU(real radius, location whichLocation){
            return GetUnitsInRangeOfLocMatchingMU(radius,   whichLocation,  Condition( \
                lambda bool(){
                    return not IsUnitType(GetFilterUnit(), UNIT_TYPE_TAUREN)
                } \
            ))
        }

        /*
        添加技能
        */
        static int UnitAddAbilityMU(unit u ,integer id,integer level){
            if id == 0
                UnitRemoveAbility(u, id)
                return 0
            elseif GetUnitAbilityLevel(u, id) == 0
                if not UnitAddAbility(u, id)
                    return 0
                endif
            endif
            UnitMakeAbilityPermanent(u, true, id)
            if GetUnitAbilityLevel(u, id) != level
                SetUnitAbilityLevel(u, id, level)
            endif
            return GetUnitAbilityLevel(u, id)
        }

        /*
        刷新单一技能冷却
        */
        static bool RefreshSkill(unit u,int id){
            int lv=GetUnitAbilityLevel(u,id)
            if lv==0
                return false
            endif
            UnitRemoveAbility(u,id)
            UnitAddAbility(u,id)
            SetUnitAbilityLevel(u,id,lv)
            Event.UnitResetCooldown_Hook(u, id)
            return true
        }

        /*
        暂停单位
        */
        static void PauseUnitMU(unit u, bool b, string flag){
            int key = StringHash("暂停:" + flag)
            int h = GetHandleId(u)
            int count = LoadInteger(YDHT, h, StringHash("全局暂停计数"))
            if b then
                if not LoadBoolean(YDHT, h, key) then
                    SaveBoolean(YDHT, h, key, true)
                    count ++
                    SaveInteger(YDHT, h, StringHash("全局暂停计数"), count)
                    if count == 1 then
                        PauseUnit(u, b)
                        //SaveReal(YDHT, h, StringHash("上次进入暂停的时间"), sys.getTime())
                        SaveUnitHandle(YDHT, StringHash("事件"), StringHash("来源"), u)
                        SaveUnitHandle(YDHT, StringHash("事件"), StringHash("目标"), u)
                        Event.UserEventStart(单位进入暂停状态)
                    endif
                endif
            else
                if LoadBoolean(YDHT, h, key) then
                    SaveBoolean(YDHT, h, key, false)
                    count --
                    SaveInteger(YDHT, h, StringHash("全局暂停计数"), count)
                    if count == 0 then
                        PauseUnit(u, b)
                        //SaveReal(YDHT, h, StringHash("上次离开暂停的时间"), sys.getTime())
                        SaveUnitHandle(YDHT, StringHash("事件"), StringHash("来源"), u)
                        SaveUnitHandle(YDHT, StringHash("事件"), StringHash("目标"), u)
                        Event.UserEventStart(单位离开暂停状态)
                    endif
                endif
            endif
        }

        /*
        单位死亡(宏)
        */
        static bool IsDead(unit u){
            return not UnitAlive(u)
        }

        #define IsUnitDeadBJ(u) Unit.IsDead(u)
        #define IsUnitAliveBJ(u) UnitAlive(u)

        /*
        移除单位
        */
        static unit r_g1[]
        static int r_i1 = 0
        static unit r_g2[]
        static int r_i2 = 0

        static void RemoveLater(unit u){
            r_g1[r_i1] = u
            r_i1 ++
        }

        static void RemoveLater_timer(){
            int i = 0
            loop
                exitwhen i == r_i2
                RemoveUnit(r_g2[i])
                i ++
            endloop
            i = 0
            loop
                exitwhen i == r_i1
                r_g2[i] = r_g1[i]
                i ++
            endloop
            r_i2 = r_i1
            r_i1 = 0
        }

        /*
        马甲攻击
        */
        static void DummyAttack(unit hero, int uid, unit target, int attack_time, bool attack_now, bool hero_state, bool hero_item, bool hero_stop){
            real x1 = GetUnitX(hero)
            real y1 = GetUnitY(hero)
            real x2 = GetUnitX(target)
            real y2 = GetUnitY(target)
            real face = Atan2BJ(y2 - y1, x2 - x1)
            unit dummy = CreateUnit(GetOwningPlayer(hero), uid, GetUnitX(hero), GetUnitY(hero), face)
            //将马甲加入清理组
            FlushUnit_Add(dummy)
            UnitAddType(dummy, UNIT_TYPE_SUMMONED)
            //设置真实来源
            SaveUnitHandle(YDHT, GetHandleId(dummy), StringHash("真实伤害来源"), hero)
            //debug@ BJDebugMsg("<马甲攻击> hero[" + GetUnitName(hero) + "] target[" + GetUnitName(target) + "] dummy[" + GetUnitName(dummy) + "]")
            if IsUnitType(dummy, UNIT_TYPE_HERO) then
                SetHeroLevel(dummy, 99, false)

                //继承英雄属性
                if hero_state then
                    SetHeroStr(dummy, GetHeroStr(hero, false), true)
                    SetHeroInt(dummy, GetHeroInt(hero, false), true)
                    SetHeroAgi(dummy, GetHeroAgi(hero, false), true)
                endif

                //继承英雄装备
                if hero_item then
                    int i = 0
                    item it
                    loop
                        exitwhen i > 5
                        it = CreateItem(GetItemTypeId(UnitItemInSlot(hero, i)), x1, y1)
                        UnitAddItem(dummy, it)
                        i ++
                    endloop
                    it = null
                endif
            endif

            //隐藏单位
            UnitAddAbility(dummy, 'Aloc')
            ShowUnit(dummy, false)

            //限定攻击目标并计数
                trigger attack_trg = CreateTrigger()

                //绑定数据
                    int h = GetHandleId(attack_trg)
                    SaveInteger(YDHT, h, 1, attack_time)
                    SaveUnitHandle(YDHT, h, 2, target)
                    SaveUnitHandle(YDHT, h, 3, dummy)

                TriggerRegisterUnitEvent(attack_trg, dummy, EVENT_UNIT_TARGET_IN_RANGE)
                TriggerRegisterUnitEvent(attack_trg, dummy, EVENT_UNIT_DEATH)
                TriggerRegisterTimerEvent(attack_trg, 10, false)

                //英雄下达其他指令时是否停止
                if hero_stop then
                    TriggerRegisterUnitEvent(attack_trg, hero, EVENT_UNIT_DEATH)
                    TriggerRegisterUnitEvent(attack_trg, hero, EVENT_UNIT_ISSUED_ORDER)
                    TriggerRegisterUnitEvent(attack_trg, hero, EVENT_UNIT_ISSUED_POINT_ORDER)
                    TriggerRegisterUnitEvent(attack_trg, hero, EVENT_UNIT_ISSUED_TARGET_ORDER)
                endif

                TriggerAddCondition(attack_trg, Condition(  \
                    lambda void(){
                        int h = GetHandleId(GetTriggeringTrigger())
                        bool flag = GetTriggerEventId() == EVENT_UNIT_TARGET_IN_RANGE
                        unit dummy = LoadUnitHandle(YDHT, h, 3)

                        //对攻击进行验证
                        if flag then
                            //取出绑定的数据
                            int attack_time = LoadInteger(YDHT, h, 1)
                            unit attack_target = LoadUnitHandle(YDHT, h, 2)
                            unit this_target = GetEventTargetUnit()
                            if attack_target == this_target then

                                //攻击正确的目标
                                attack_time --
                                if attack_time < 0 then

                                    //耗尽攻击次数,移除单位
                                    flag = false
                                else
                                    SaveInteger(YDHT, h, 1, attack_time)
                                endif
                            else
                                flag = false
                            endif

                            //回收
                            attack_target = null
                            this_target = null
                        endif

                        //判断是否该移除攻击马甲
                        if not flag then
                            PauseUnit(dummy, true)
                            RemoveLater(dummy)
                            DestroyTrigger(GetTriggeringTrigger())
                            FlushChildHashtable(YDHT, h)
                        endif

                        dummy = null

                    }   \
                ))

            //是否立刻进行攻击
            if attack_now then
                IssueTargetOrder(dummy, "attack", target)
            endif

            //回收
            bj_lastCreatedUnit = dummy
            dummy = null
            attack_trg = null
        }

        /*
        删除单位组
        */
        define <call Unit.WantDestroyGroup()> = {set bj_wantDestroyGroup = true}

        /*
        马甲放技能(第5个参数在保存地图时通过lua进行设置)
        */
        static unit dummy[]

        //保存地图时根据技能id生成第5个参数
        <?
            update('war3map.j', 'Unit.DummySkill',
                function(content)
                    content = content:gsub("(Unit.DummySkill%a-%(%C+)",
                        function(s)
                            local flag
                            s = s:gsub("(.+')(%w+)(')",
                                function(s1, sid, s3)
                                    flag = true
                                    local ab = slk.ability[sid]
                                    if tonumber(ab.Rng1) < 5000 then
                                        error(('%s[%s]%s(%d)'):format(string.char(188, 188, 196, 220), sid, string.char(181, 196, 202, 169, 183, 168, 190, 224, 192, 235, 204, 171, 182, 204, 193, 203), ab.Rng1))
                                    end
                                    if tonumber(ab.Cost1) ~= 0 then
                                        error(('%s[%s]%s(%d)'):format(string.char(188, 188, 196, 220), sid, string.char(181, 196, 196, 167, 183, 168, 207, 251, 186, 196, 178, 187, 202, 199, 48), ab.Cost1))
                                    end
                                    if tonumber(ab.Cool1) ~= 0 then
                                        error(('%s[%s]%s(%d)'):format(string.char(188, 188, 196, 220), sid, string.char(181, 196, 192, 228, 200, 180, 202, 177, 188, 228, 178, 187, 206, 170, 48), ab.Cool1))
                                    end
                                    if tonumber(ab.Cast1) ~= 0 then
                                        error(('%s[%s]%s(%d)'):format(string.char(188, 188, 196, 220), sid, string.char(181, 196, 202, 169, 183, 168, 202, 177, 188, 228, 178, 187, 202, 199, 48), ab.Cast1))
                                    end
                                    local order_id
                                    if not ab.Order or ab.Order == '' then
                                        order_id = ab.YDWEtip:sub(-6, -1)
                                    else
                                        order_id = order2id[ab.Order]
                                    end
                                    return ([[%s%s%s, %s]]):format(s1, sid, s3, order_id)
                                end
                            )
                            if not flag then
                                error(('%s\n%s'):format(string.char(188, 188, 196, 220, 182, 193, 200, 161, 202, 167, 176, 220, 44, 199, 235, 200, 183, 200, 207, 188, 188, 196, 220, 204, 238, 181, 196, 181, 196, 190, 178, 204, 172, 214, 181, 40, 178, 187, 196, 220, 211, 195, 177, 228, 193, 191, 41), s))
                            end
                            return s
                        end
                    )

                    return content
                end
            )
        ?>

        static int DummySkill_lastSkill[]
        static int DummySkill_lastLv[]

        static void DummySkill(player p, unit u, int lv, int sid, int order){
            int i = GetPlayerId(p)
            if sid == DummySkill_lastSkill[i] then
                if lv != DummySkill_lastLv[i] then
                    SetUnitAbilityLevel(dummy[i], sid, lv)
                    DummySkill_lastLv[i] = lv
                endif
            else
                UnitRemoveAbility(dummy[i], DummySkill_lastSkill[i])
                UnitAddAbility(dummy[i], sid)
                if lv != 1 then
                    SetUnitAbilityLevel(dummy[i], sid, lv)
                endif
                DummySkill_lastSkill[i] = sid
                DummySkill_lastLv[i] = lv
            endif
            if IsUnitInvisible(u, p) then
                UnitShareVision(u, p, true)
                IssueTargetOrderById(dummy[i], order, u)
                UnitShareVision(u, p, false)
            else
                IssueTargetOrderById(dummy[i], order, u)
            endif
        }

        static void DummySkillLoc(player p, location loc, bool b, int lv, int sid, int order){
            int i = GetPlayerId(p)
            if sid == DummySkill_lastSkill[i] then
                if lv != DummySkill_lastLv[i] then
                    SetUnitAbilityLevel(dummy[i], sid, lv)
                    DummySkill_lastLv[i] = lv
                endif
            else
                UnitRemoveAbility(dummy[i], DummySkill_lastSkill[i])
                UnitAddAbility(dummy[i], sid)
                if lv != 1 then
                    SetUnitAbilityLevel(dummy[i], sid, lv)
                endif
                DummySkill_lastSkill[i] = sid
                DummySkill_lastLv[i] = lv
            endif
            IssuePointOrderByIdLoc(dummy[i], order, loc)
            if b then
                RemoveLocation(loc)
            endif
        }

        static void DummySkill_Init(){
            int i = 0
            loop
                exitwhen i > 15
                if i == 12 then
                    dummy[i] = CreateUnit(Player(15), 'e010', 0, 0, 0)
                else
                    dummy[i] = CreateUnit(Player(i), 'e010', 0, 0, 0)
                endif
                i ++
            endloop
        }

        /*
        设置单位硬直
        */
        static trigger SetHard_trg = CreateTrigger()

        static void SetHard(unit u, real time){
            int h = GetHandleId(u)
            if time == 0 then
                //解除硬直
                PauseTimer(LoadTimerHandle(YDHT, h, StringHash("硬直计时器")))
                SaveBoolean(YDHT, h, StringHash("是否处于硬直状态"), false)
                UnitRemoveAbility(u, 'B02O')
            else
                if GetUnitAbilityLevel(u, 'B02O') == 0 and GetUnitAbilityLevel(u, 'BPSE') == 0 then
                    Unit.DummySkill(GetOwningPlayer(u), u, 1, 'A0PY')
                endif

                timer t = LoadTimerHandle(YDHT, h, StringHash("硬直计时器"))

                if not LoadBoolean(YDHT, h, StringHash("已注册硬直事件")) then
                    SaveBoolean(YDHT, h, StringHash("已注册硬直事件"), true)
                    TriggerRegisterUnitEvent(SetHard_trg, u, EVENT_UNIT_DAMAGED)
                    TriggerRegisterUnitEvent(SetHard_trg, u, EVENT_UNIT_ISSUED_ORDER)
                    TriggerRegisterUnitEvent(SetHard_trg, u, EVENT_UNIT_ISSUED_POINT_ORDER)
                    TriggerRegisterUnitEvent(SetHard_trg, u, EVENT_UNIT_ISSUED_TARGET_ORDER)

                    t = CreateTimer()
                    SaveTimerHandle(YDHT, h, StringHash("硬直计时器"), t)
                    SaveUnitHandle(YDHT, GetHandleId(t), 0, u)
                endif

                SaveBoolean(YDHT, h, StringHash("是否处于硬直状态"), true)

                TimerStart(t, time, false, \
                    lambda void(){
                        int th = GetHandleId(GetExpiredTimer())
                        unit u = LoadUnitHandle(YDHT, th, 0)
                        int h = GetHandleId(u)
                        SaveBoolean(YDHT, h, StringHash("是否处于硬直状态"), false)
                        UnitRemoveAbility(u, 'B02O')
                        u = null
                    }\
                )

                if LoadInteger(YDHT, h, StringHash("全局暂停计数")) != 0 then
                    PauseTimer(t)
                endif
                t = null
            endif
        }

        static void SetHard_Init(){
            TriggerAddCondition(SetHard_trg, Condition(\
                lambda void(){
                    if GetTriggerEventId() != EVENT_UNIT_DAMAGED or GetEventDamage() == 0 then
                        unit u = GetTriggerUnit()
                        int h = GetHandleId(u)
                        if LoadBoolean(YDHT, h, StringHash("是否处于硬直状态")) and GetUnitAbilityLevel(u, 'B02O') == 0 and GetUnitAbilityLevel(u, 'BPSE') == 0 then
                            DisableTrigger(SetHard_trg)
                            if not IsUnitPaused(u) then
                                PauseUnit(u, true)
                                PauseUnit(u, false)
                            endif
                            Unit.DummySkill(GetOwningPlayer(u), u, 1, 'A0PY')
                            EnableTrigger(SetHard_trg)
                        endif
                        u = null
                    endif
                } \
            ))

            trigger trg = CreateTrigger()
            Event.UserEventInit(trg, 单位进入暂停状态)
            Event.UserEventInit(trg, 单位离开暂停状态)
            TriggerAddCondition(trg, Condition(\
                lambda void(){
                    unit u  = LoadUnitHandle(YDHT, StringHash("事件"), StringHash("来源"))
                    int h   = GetHandleId(u)
                    if LoadBoolean(YDHT, h, StringHash("是否处于硬直状态")) then
                        timer t = LoadTimerHandle(YDHT, h, StringHash("硬直计时器"))
                        if LoadStr(YDHT, StringHash("事件"), StringHash("名称")) == "单位进入暂停状态" then
                            PauseTimer(t)
                        else
                            TimerStart(t, TimerGetRemaining(t), false, \
                                lambda void(){
                                    int th = GetHandleId(GetExpiredTimer())
                                    unit u = LoadUnitHandle(YDHT, th, 0)
                                    int h = GetHandleId(u)
                                    SaveBoolean(YDHT, h, StringHash("是否处于硬直状态"), false)
                                    UnitRemoveAbility(u, 'B02O')
                                    u = null
                                }\
                            )
                        endif
                    endif
                    u = null
                } \
            ))
            trg = null
        }

        static bool IsHard(unit u){
            return LoadBoolean(YDHT, GetHandleId(u), StringHash("是否处于硬直状态")) or GetUnitAbilityLevel(u, 'B02O') == 1
        }

        /*
        设置单位可以飞行(宏)
        */
        static void FlyEnable(unit u){
            UnitAddAbility(u, 'Arav')
            UnitRemoveAbility(u, 'Arav')
        }

        #define YDWEFlyEnable(u) Unit.FlyEnable(u)

        /*
        创建技能施法进度条
        */
        static unit lastSkillBar = null

        static void SkillBar_Dead(unit bar, bool out){
            FlushChildHashtable(YDHT, GetHandleId(bar))
            if not out then
                RemoveUnit(bar)
                return
            endif

            timer t = CreateTimer()
            int h   = GetHandleId(t)
            
            SetUnitColor(bar, PLAYER_COLOR_LIGHT_GRAY)

            SaveUnitHandle(YDHT, h, 0, bar)
            SaveInteger(YDHT, h, 0, 255)
            
            TimerStart(t, 0.05, true,\
                lambda void(){
                    int h       = GetHandleId(GetExpiredTimer())
                    unit bar    = LoadUnitHandle(YDHT, h, 0)
                    int a       = LoadInteger(YDHT, h, 0)

                    a -= 10
                    SetUnitVertexColor(bar, 255, 255, 255, a)

                    if a <= 0 then
                        RemoveUnit(bar)
                        DestroyTimer(GetExpiredTimer())
                        FlushChildHashtable(YDHT, h)
                    else
                        SaveInteger(YDHT, h, 0, a)
                    endif

                    bar = null
                }\
            )
            t   = null
        }

        static unit SkillBar(unit hero, real time, playercolor color, bool pause, bool die, bool stop, bool out){
            unit bar    = CreateUnit(GetOwningPlayer(hero), 'e06I', GetUnitX(hero), GetUnitY(hero), 0)
            trigger trg = CreateTrigger()
            int h       = GetHandleId(trg)
            real scale  = 1 / time
            int order   = GetUnitCurrentOrder(hero)

            SetUnitColor(bar, color)

            if time > 0 then
                SetUnitAnimation(bar, "birth")
            else
                SetUnitAnimation(bar, "attack")
                time    = - time
                scale   = - scale
            endif

            SetUnitTimeScale(bar, scale)

            //创建触发器
            SaveUnitHandle(YDHT, h, 0, bar)
            SaveUnitHandle(YDHT, h, 1, hero)
            SaveBoolean(YDHT, h, 1, pause)
            SaveBoolean(YDHT, h, 2, die)
            SaveBoolean(YDHT, h, 3, stop)
            SaveBoolean(YDHT, h, 4, out)
            SaveReal(YDHT, h, 0, time)
            SaveReal(YDHT, h, 1, scale)
            SaveInteger(YDHT, h, 0, order)
            
            //添加事件
            
            TriggerRegisterTimerEvent(trg, 0.03, true)
            TriggerRegisterUnitEvent(trg, bar, EVENT_UNIT_DEATH)
            
            if die then
                TriggerRegisterUnitEvent(trg, hero, EVENT_UNIT_DEATH)
            endif
            
            if stop then
                TriggerRegisterUnitEvent(trg, hero, EVENT_UNIT_SPELL_ENDCAST)
                TriggerRegisterUnitEvent(trg, hero, EVENT_UNIT_SPELL_FINISH)
            endif
            
            TriggerAddCondition(trg, Condition(\
                lambda void (){
                    int h       = GetHandleId(GetTriggeringTrigger())
                    unit bar    = LoadUnitHandle(YDHT, h, 0)
                    unit hero   = LoadUnitHandle(YDHT, h, 1)
                    bool pause  = LoadBoolean(YDHT, h, 1)
                    bool die    = LoadBoolean(YDHT, h, 2)
                    bool stop   = LoadBoolean(YDHT, h, 3)
                    bool out    = LoadBoolean(YDHT, h, 4)
                    real time   = LoadReal(YDHT, h, 0)
                    real scale  = LoadReal(YDHT, h, 1)
                    real order  = LoadInteger(YDHT, h, 0)
                    if IsUnitType(bar, UNIT_TYPE_DEAD) or (die and IsUnitType(hero, UNIT_TYPE_DEAD)) or GetTriggerEventId() == EVENT_UNIT_SPELL_ENDCAST then

                        trigger trg = LoadTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能失败"))
                        if trg != null then
                            if IsTriggerEnabled(trg) and TriggerEvaluate(trg) then
                                TriggerExecute(trg)
                            endif
                            FlushChildHashtable(YDHT, GetHandleId(trg))
                            DestroyTrigger(trg)
                            trg = null
                        endif

                        trg = LoadTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能成功"))
                        if trg != null then
                            FlushChildHashtable(YDHT, GetHandleId(trg))
                            DestroyTrigger(trg)
                            trg = null
                        endif

                        SetUnitTimeScale(bar, 0)
                        SkillBar_Dead(bar, out)
                        DestroyTrigger(GetTriggeringTrigger())
                        FlushChildHashtable(YDHT, h)
                    elseif pause and IsUnitPaused(hero) then
                        SetUnitTimeScale(bar, 0)
                        PauseUnit(bar, true)
                    elseif GetTriggerEventId() == EVENT_GAME_TIMER_EXPIRED then
                        if IsUnitPaused(bar) then
                            SetUnitTimeScale(bar, scale)
                            PauseUnit(bar, false)
                        endif
                        SetUnitX(bar, GetUnitX(hero))
                        SetUnitY(bar, GetUnitY(hero))
                        SetUnitFlyHeight(bar, 225 + maphack.GetHeight(hero), 0)
                        time -= 0.03
                    endif
                    
                    if time <= 0 or GetTriggerEventId() == EVENT_UNIT_SPELL_FINISH then
                    
                        trigger trg = LoadTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能成功"))
                        if trg != null then
                            if IsTriggerEnabled(trg) and TriggerEvaluate(trg) then
                                TriggerExecute(trg)
                            endif
                            FlushChildHashtable(YDHT, GetHandleId(trg))
                            DestroyTrigger(trg)
                            trg = null
                        endif

                        trg = LoadTriggerHandle(YDHT, GetHandleId(bar), StringHash("技能失败"))
                        if trg != null then
                            FlushChildHashtable(YDHT, GetHandleId(trg))
                            DestroyTrigger(trg)
                            trg = null
                        endif

                        SetUnitTimeScale(bar, 0)
                        SkillBar_Dead(bar, out)
                        DestroyTrigger(GetTriggeringTrigger())
                        FlushChildHashtable(YDHT, h)
                    else
                        SaveReal(YDHT, h, 0, time)
                    endif

                    bar = null
                    hero = null
                }\
            ))

            lastSkillBar = bar
            trg = null
            bar = null

            return lastSkillBar
        }

        static void AddMoveSpeed(unit u, real r){
            int h       = GetHandleId(u)
            real ms0    = GetUnitDefaultMoveSpeed(u)
            real ms1    = LoadReal(YDHT, h, StringHash("额外移动速度")) + r
            SaveReal(YDHT, h, StringHash("额外移动速度"), ms1)
            SetUnitMoveSpeed(u, ms0 + ms1)
        }

        /*
        单位的Z轴高度
        */
        static location z_location  = Location(0, 0)

        static real GetUnitZ(unit u){
            MoveLocation(z_location, GetUnitX(u), GetUnitY(u))
            return GetLocationZ(z_location) + GetUnitFlyHeight(u)
        }

        static void SetUnitZ(unit u, real z){
            MoveLocation(z_location, GetUnitX(u), GetUnitY(u))
            SetUnitFlyHeight(u, z - GetLocationZ(z_location), 0)
        }

        //获取单位护甲值
        static real GetUnitDefence(unit u){
            if sys.isIn11() then
                return GetUnitState(u, ConvertUnitState(0x20))
            endif

            //伤害测试法算护甲
            real hp0 = GetWidgetLife(u)
            SetWidgetLife(u, hp0 + 10)
            real hp1 = GetWidgetLife(u)

            //关掉伤害系统
            Event.damageEvent_Enable = false

            //造成测试伤害
            UnitDamageTarget(u, u, 10, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)

            //重新打开伤害系统
            Event.damageEvent_Enable = true

            real hp2 = GetWidgetLife(u)

            //恢复生命值
            SetWidgetLife(u, hp1)

            //算出伤害
            real dam = hp1 - hp2
            if dam <= 0 then
                return 0.
            endif

            //找到护甲免伤参数
            <?
                update('war3mapmisc.txt', '护甲免伤',
                    function(content)
                        DEF_ARMOR = content:match 'DefenseArmor%=(%C+)'
                    end
                )

            ?>

            //求出护甲值
            return (10. / dam - 1) / <?=DEF_ARMOR?>
        }

        /*
        脚本发布指令
        */

        //是否是脚本下达的指令
        static bool IsOrderedByScript = false

        /*
        发布命令(指定目标)
        */

        static bool IssueTargetOrder2(unit u, string o, unit t){
            bool b
            IsOrderedByScript = true
            if GetUnitAbilityLevel(u, 'Aloc') == 1 then
                player p = GetOwningPlayer(u)
                if IsUnitInvisible(t, p) then
                    UnitShareVision(t, p, true)
                    b = IssueTargetOrder(u, o, t)
                    UnitShareVision(t, p, false)
                    p = null
                else
                    b = IssueTargetOrder(u, o, t)
                endif
                p = null
            else
                b = IssueTargetOrder(u, o, t)
            endif
            IsOrderedByScript = false
            return b
        }

        static bool IssueTargetOrderById2(unit u, integer o, unit t){
            bool b
            IsOrderedByScript = true
            if GetUnitAbilityLevel(u, 'Aloc') == 1 then
                player p = GetOwningPlayer(u)
                if IsUnitInvisible(t, p) then
                    UnitShareVision(t, p, true)
                    b = IssueTargetOrderById(u, o, t)
                    UnitShareVision(t, p, false)
                    p = null
                 else
                    b = IssueTargetOrderById(u, o, t)
                endif
                p = null
            else
                b = IssueTargetOrderById(u, o, t)
            endif
            IsOrderedByScript = false
            return b
        }

        #define IssueTargetOrder(u, o, t) Unit.IssueTargetOrder2(u, o, t)
        #define IssueTargetOrderBJ(u, o, t) Unit.IssueTargetOrder2(u, o, t)
        #define IssueTargetOrderById(u, o, t) Unit.IssueTargetOrderById2(u, o, t)

        /*
        发布命令(坐标点)
        */

        static bool IssuePointOrder2(unit u, string o, real x, real y){
            IsOrderedByScript = true
            bool b = IssuePointOrder(u, o, x, y)
            IsOrderedByScript = false
            return b
        }

        static bool IssuePointOrderById2(unit u, int o, real x, real y){
            IsOrderedByScript = true
            bool b = IssuePointOrderById(u, o, x, y)
            IsOrderedByScript = false
            return b
        }

        #define IssuePointOrder(u, o, x, y) Unit.IssuePointOrder2(u, o, x, y)
        #define IssuePointOrderById(u, o, x, y) Unit.IssuePointOrderById2(u, o, x, y)

        /*
        发布命令(点)
        */

        static bool IssuePointOrderLoc2(unit u, string o, location l){
            IsOrderedByScript = true
            bool b = IssuePointOrderLoc(u, o, l)
            IsOrderedByScript = false
            return b
        }

        static bool IssuePointOrderByIdLoc2(unit u, int o, location l){
            IsOrderedByScript = true
            bool b = IssuePointOrderByIdLoc(u, o, l)
            IsOrderedByScript = false
            return b
        }

        #define IssuePointOrderLoc(u, o, l) Unit.IssuePointOrderLoc2(u, o, l)
        #define IssuePointOrderLocBJ(u, o, l) Unit.IssuePointOrderLoc2(u, o, l)
        #define IssuePointOrderByIdLoc(u, o, l) Unit.IssuePointOrderByIdLoc2(u, o, l)

        /*
        发布命令(点)
        自动清除引用点
        */
        static bool IssuePointOrderLocMU(unit u, string id, location loc){
            IsOrderedByScript = true
            local boolean result = IssuePointOrderLoc(u,id,loc)
            RemoveLocation(loc)
            IsOrderedByScript = false
            return result
        }

        static bool IssuePointOrderByIdLocMU(unit u, integer id, location loc){
            IsOrderedByScript = true
            local boolean result = IssuePointOrderByIdLoc(u,id,loc)
            RemoveLocation(loc)
            IsOrderedByScript = false
            return result
        }

        /*
        发布命令(无目标)
        */
        static bool IssueImmediateOrder2(unit u, string o){
            IsOrderedByScript = true
            bool b = IssueImmediateOrder(u, o)
            IsOrderedByScript = false
            return b
        }

        static bool IssueImmediateOrderById2(unit u, int o){
            IsOrderedByScript = true
            bool b = IssueImmediateOrderById(u, o)
            IsOrderedByScript = false
            return b
        }

        #define IssueImmediateOrder(u, o) Unit.IssueImmediateOrder2(u, o)
        #define IssueImmediateOrderBJ(u, o) Unit.IssueImmediateOrder2(u, o)
        #define IssueImmediateOrderById(u, o) Unit.IssueImmediateOrderById2(u, o)
        
        //注册物编数据
        //Unit.SaveSlkData( 'unit_type_id', slk_name1 slk_name2 slk_name3 )
        <?
            update('war3map.j', '注册物编数据',
                function(content)
                    content = content:gsub("call Unit%.SaveSlkData%( '(....)'%, (%C+) %)",
                        function(unit_type_id, slk_names)
                            local lines = {}
                            local unit_slk  = slk.unit[unit_type_id]
                            for name in slk_names:gmatch '%S+' do
                                local data  = unit_slk[name]
                                --判断数据类型
                                if tonumber(data) then
                                    --数字
                                    if data:match '%.' then
                                        --实数
                                        table.insert(lines, ("call SaveReal(YDHT, '%s', %s, %s)"):format(unit_type_id, string_hash(name), data))
                                    else
                                        --整数
                                        table.insert(lines, ("call SaveInteger(YDHT, '%s', %s, %s)"):format(unit_type_id, string_hash(name), data))
                                    end
                                else
                                    --字符串类型
                                    table.insert(lines, ("call SaveStr(YDHT, '%s', %s, %s)"):format(unit_type_id, string_hash(name), data))
                                end
                            end
                            
                            return table.concat(lines, '\r\n')
                        end 
                    )
                    
                    return content
                end
            )
        ?>
        
        //恢复单位默认颜色
        static void ResetVertexColor(unit u){
            int id = GetUnitTypeId(u)
            int red = 255, green = 255, blue = 255
            if HaveSavedInteger(YDHT, id, StringHash("red")) then
                red = LoadInteger(YDHT, id, StringHash("red"))
            endif
            if HaveSavedInteger(YDHT, id, StringHash("green")) then
                red = LoadInteger(YDHT, id, StringHash("green"))
            endif
            if HaveSavedInteger(YDHT, id, StringHash("blue")) then
                red = LoadInteger(YDHT, id, StringHash("blue"))
            endif
            SetUnitVertexColor(u, red, green, blue, 255)
        }
        
        /*
        治疗单位
        */
        static void Heal(unit from, unit to, real heal){
            real life = GetWidgetLife(to)
            real max_life = GetUnitState(to, UNIT_STATE_MAX_LIFE)
            
            //预留事件
            
            life += heal
            SetWidgetLife(to, life)
        }
        
        /*
        添加暴击模块
        */
        static int last_CritAddedUnitHandle = 0
        static int last_CritAddedTriggerHandle = 0
        static int last_CritAddedCount = 0
        
        static void Crit(unit u, bool add, real chance, real rate, string tag, int crit_type){
            //先检查参数合法性
            if chance <= 0 or rate <= 0 or GetUnitTypeId(u) == 0 then
                return
            endif
            
            //是暴击模块还是被暴击模块
            int hash_count, hash_chance, hash_rate, hash_tag, hash_trigger
            
            if crit_type == 0 then
                hash_count   = StringHash("暴击模块计数")
                hash_chance  = StringHash("暴击几率值段")
                hash_rate    = StringHash("暴击倍率值段")
                hash_tag     = StringHash("暴击标签值段")
                hash_trigger = StringHash("暴击触发值段")
            elseif crit_type == 1 then
                hash_count   = StringHash("被暴击模块计数")
                hash_chance  = StringHash("被暴击几率值段")
                hash_rate    = StringHash("被暴击倍率值段")
                hash_tag     = StringHash("被暴击标签值段")
                hash_trigger = StringHash("被暴击触发值段")
            endif
            
            int h       = GetHandleId(u)
            int count   = LoadInteger(YDHT, h, hash_count)
            
            if add then
            
                //在暴击模块队列末端添加新的暴击模块
                count   = count + 1
                SaveReal(YDHT, h, hash_chance + count, chance)
                SaveReal(YDHT, h, hash_rate + count, rate)
                SaveStr(YDHT, h, hash_tag + count, tag)
                RemoveSavedHandle(YDHT, h, hash_trigger + count)
                
                //保存计数
                SaveInteger(YDHT, h, hash_count, count)
                
                //保存全局变量
                last_CritAddedUnitHandle = h
                last_CritAddedTriggerHandle = hash_trigger
                last_CritAddedCount = hash_count
                
            else
                //找到完全匹配的模块才可以移除
                int i   = 1
                loop
                    exitwhen i > count
                    if chance == LoadReal(YDHT, h, hash_chance + i)\
                    and rate  == LoadReal(YDHT, h, hash_rate + i)\
                    and tag   == LoadStr(YDHT, h, hash_tag + i) then
                    
                        //清空当前暴击模块的触发
                        trigger trg = LoadTriggerHandle(YDHT, h, hash_trigger + i)
                        DestroyTrigger(trg)
                        FlushChildHashtable(YDHT, GetHandleId(trg))
                        trg = null
                        
                        //将队列最后的暴击模块移动到当前位置
                        SaveReal(YDHT, h, hash_chance + i, LoadReal(YDHT, h, hash_chance + count))
                        SaveReal(YDHT, h, hash_rate + i, LoadReal(YDHT, h, hash_rate + count))
                        SaveStr(YDHT, h, hash_tag + i, LoadStr(YDHT, h, hash_tag + count))
                        SaveTriggerHandle(YDHT, h, hash_trigger + i, LoadTriggerHandle(YDHT, h, hash_trigger + count))
                        
                        //保存计数
                        SaveInteger(YDHT, h, hash_count, count - 1)
                        return
                    endif
                    i ++
                endloop
                
                //没有找打匹配的暴击模块,报错
                BJDebugMsg("<错误>没有找到要移除的暴击模块!")
                BJDebugMsg("<单位>" + GetUnitName(u))
                BJDebugMsg("<几率>" + R2S(chance))
                BJDebugMsg("<倍率>" + R2S(rate))
                BJDebugMsg("<标签>" + tag)
            endif
        }
        
        /*
        实数转换为字符串（自动省略小数点）
        */
        
        static string R2SS(real a){
            int b
            string str
            b = R2I(a)
            a = a - I2R(b)
            if a == 0 then
                str = I2S(b)
                return str
            endif
            str = I2S(b) + "."
            loop
                exitwhen a == 0 || StringLength(str)>=6
                a = a * 10
                b = R2I(a)
                a = a - I2R(b)
                str = str + I2S(b)
            endloop
            return str
        }
        
        /*
        打印命中/闪避模块
        */
        
        static void PrintHitDodgCrit(unit u,int mode,player pl){
            //检查合法性
            if GetUnitTypeId(u) == 0 then
                return
            endif
            int hash_count, hash_chance, hash_tag, hash_rate,h = GetHandleId(u)
            real chance, rate, ch=100, im
            string mo, tag  = ""
            //判断模式
            if mode == 0 then     //命中
                hash_count   = StringHash("命中模块计数")
                hash_chance  = StringHash("命中几率值段")
                hash_tag     = StringHash("命中标签值段")
                mo           = "|cFFFFCC33命中"
            else 
                if mode == 1 then //闪躲
                    hash_count   = StringHash("闪躲模块计数")
                    hash_chance  = StringHash("闪躲几率值段")
                    hash_tag     = StringHash("闪躲标签值段")
                    mo           = "|cFF33FFFF闪躲"
                else              //暴击
                    hash_count   = StringHash("暴击模块计数")
                    hash_chance  = StringHash("暴击几率值段")
                    hash_rate    = StringHash("暴击倍率值段")
                    hash_tag     = StringHash("暴击标签值段")
                    mo           = "|cFFFF0000暴击"
                    im           = LoadReal(YDHT, h, StringHash("暴击几率加成"))
                endif
            endif
            
            int count   = LoadInteger(YDHT, h, hash_count)
            int i       = 1
            
            if count < i then
                call DisplayTextToPlayer( pl, 0, 0, "单位 |cFFCCFF00" + GetUnitName(u) +"|r 目前没有 " + mo + "模块|r")
                return
            else
                call DisplayTextToPlayer( pl, 0, 0, "\n单位 |cFFCCFF00" + GetUnitName(u) +"|r 的 " + mo + "模块|r" + " 有：" )
            endif
            loop 
                exitwhen i > count
                chance = LoadReal(YDHT, h, hash_chance + i)
                tag    = LoadStr(YDHT, h, hash_tag + i) 
                //暴击模块额外打印倍率
                if mode == 2 then
                    rate   = LoadReal(YDHT, h, hash_rate + i)
                    //是否有暴击几率加成
                    if im == 0 then
                        call DisplayTextToPlayer( pl, 0, 0, "标签为 |cFFCCCCFF" + tag + "|r 的 " + R2SS(chance) + "% 的 " + R2SS(rate) + "倍 " + mo + "模块|r")
                    else
                        call DisplayTextToPlayer( pl, 0, 0, "标签为 |cFFCCCCFF" + tag + "|r 的 " + R2SS(chance) + "%(+" + R2SS(im*100) + "%) 的 " + R2SS(rate) + "倍 " + mo + "模块|r")
                    endif
                else
                    ch -= ch * chance / 100
                    call DisplayTextToPlayer( pl, 0, 0, "标签为 |cFFCCCCFF" + tag + "|r 的 " + R2SS(chance) + "% 的 " + mo + "模块|r")
                endif
                i ++
            endloop
            //如果是查询命中和闪避模块 额外打印总和
            if mode != 2 then
                ch = 100 - ch
                call DisplayTextToPlayer( pl, 0, 0, "单位的额外 " + mo + "|r几率为 " + R2S(ch) + "%")
            endif
            return
        }
        
        /*
        添加命中/闪躲模块
        */
        
        static void HitDodg(unit u, bool add, real chance, string tag, int hit_dodge){
            //检查合法性
            if chance == 0 or GetUnitTypeId(u) == 0 then
                return
            endif
            
            //是命中还是闪躲
            int hash_count, hash_chance, hash_tag
            
            if hit_dodge == 0 then
                hash_count   = StringHash("命中模块计数")
                hash_chance  = StringHash("命中几率值段")
                hash_tag     = StringHash("命中标签值段")
            else
                hash_count   = StringHash("闪躲模块计数")
                hash_chance  = StringHash("闪躲几率值段")
                hash_tag     = StringHash("闪躲标签值段")
            endif
            
            int h       = GetHandleId(u)
            int count   = LoadInteger(YDHT, h, hash_count)
            
            if add then
            
                //在模块队列末端添加新的模块
                count   = count + 1
                SaveReal(YDHT, h, hash_chance + count, chance)
                SaveStr(YDHT, h, hash_tag + count, tag)
                
                //保存计数
                SaveInteger(YDHT, h, hash_count, count)                
            else
                //找到完全匹配的模块才可以移除
                int i   = 1
                loop
                    exitwhen i > count
                    if chance == LoadReal(YDHT, h, hash_chance + i)\
                    and tag   == LoadStr(YDHT, h, hash_tag + i) then
                        
                        //将队列最后的模块移动到当前位置
                        SaveReal(YDHT, h, hash_chance + i, LoadReal(YDHT, h, hash_chance + count))
                        SaveStr(YDHT, h, hash_tag + i, LoadStr(YDHT, h, hash_tag + count))
                        
                        //保存计数
                        SaveInteger(YDHT, h, hash_count, count - 1)
                        return
                    endif
                    i ++
                endloop
                
                //没有找打匹配的模块,报错
                BJDebugMsg("<错误>没有找到要移除的命中/闪躲模块!")
                BJDebugMsg("<单位>" + GetUnitName(u))
                BJDebugMsg("<几率>" + R2S(chance))
                BJDebugMsg("<标签>" + tag)
            endif
        }
        
        /*
        命中/闪躲结算
        */
        //#define DODG_MAGIC_BOOK 'A07L'
        //#define HIT_MAGIC_BOOK 'A901'
        
        static trigger HIT_DODG_TRIGGER = CreateTrigger()

        static void initHitDodg(){
            /*
            int i = 0
            loop
                exitwhen i > 11
                SetPlayerAbilityAvailable(Player(i), DODG_MAGIC_BOOK, false)
                SetPlayerAbilityAvailable(Player(i), HIT_MAGIC_BOOK, false)
                i ++
            endloop
            */
            
            //命中/闪躲结算
            TriggerAddCondition(HIT_DODG_TRIGGER, Condition(\
                lambda void (){
                    Event.index ++
                    
                    Event.u_from[Event.index] = GetTriggerUnit()
                    Event.u_to[Event.index] = GetEventTargetUnit()
                    
                    real hit, dodg, thisHit = 100, thisDodg = 100 //当前命中和闪躲都是取倒值
                    int i, h, count, disable
                    
                    //先结算命中
                    h = GetHandleId(Event.u_from[Event.index])
                    //命中模块是否无效
                    disable = LoadInteger(YDHT, h, StringHash("命中模块无效"))
                    count = LoadInteger(YDHT, h, StringHash("命中模块计数"))
                    i = 1
                    loop
                        exitwhen i > count
                        hit = LoadReal(YDHT, h, StringHash("命中几率值段") + i)
                        if hit > 0 then
                            if disable == 0 then
                                thisHit -= thisHit * hit / 100
                            endif
                        elseif thisDodg > 0 then
                            thisDodg += thisDodg * hit / 100
                        endif
                        i ++
                    endloop
                    
                    //再结算闪躲
                    h = GetHandleId(Event.u_to[Event.index])
                    count = LoadInteger(YDHT, h, StringHash("闪躲模块计数"))
                    i = 1
                    loop
                        exitwhen i > count
                        dodg = LoadReal(YDHT, h, StringHash("闪躲几率值段") + i)
                        if dodg > 0 then
                            thisDodg -= thisDodg * dodg / 100
                        elseif thisHit > 0 then
                            thisHit += thisHit * dodg / 100
                        endif
                        i ++
                    endloop
                    
                    thisHit = (100 - thisHit) * (1 + LoadReal(YDHT, h, StringHash("命中几率加成")))
                    thisDodg = (100 - thisDodg) * (1 + LoadReal(YDHT, h, StringHash("闪躲几率加成")))
                    
                    //闪避=闪避×（1-命中×0.25）-命中×0.6    这个闪躲公式是shenmegui
                    real chance = thisDodg - thisDodg * thisHit / 400 - thisHit * 0.6
                    
                    //进行闪躲判定
                    if chance > 0 and chance >= GetRandomReal(0, 100) then
                        //攻击miss
                        Unit.DummySkill(Player(15), Event.u_from[Event.index], 1, 'A0XK')
                    else
                        //攻击命中
                        UnitRemoveAbility(Event.u_from[Event.index], 'B04B')
                    endif
                    
                    Event.index --
                }\
            ))
            
            //重置攻击动画
            trigger trg = CreateTrigger()
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ATTACKED)
            TriggerAddCondition(trg, Condition(\
                lambda void(){
                    SetUnitAnimation(GetAttacker(), "attack")
                }\
            ))

            //命中/闪躲结算触发器
            trg = CreateTrigger()
            Event.UserEventInit(trg, 任意单位被创建)
            TriggerAddCondition(trg, Condition(\
                lambda void(){
                    TriggerRegisterUnitEvent(HIT_DODG_TRIGGER, LoadUnitHandle(YDHT, StringHash("事件"), StringHash("目标")), EVENT_UNIT_TARGET_IN_RANGE)
                }\
            ))
            
            trg = null
        }
        //#undef DODG_MAGIC_BOOK
        //#undef HIT_MAGIC_BOOK
        
        /*
        获取单位最大生命值(修正伤害减免系统带来的误差)
        */
        static real GetMaxLife(unit u){
            if GetUnitAbilityLevel(u, 'A0RJ') == 0 then
                return GetUnitState(u, UNIT_STATE_MAX_LIFE)
            else
                return GetUnitState(u, UNIT_STATE_MAX_LIFE) - <?=slk.ability.A0RJ.DataA1?>
            endif
        }
        
        static real GetLifePercent(unit u){
            real max_life = GetMaxLife(u)
            if max_life == 0 then
                return 0.
            else
                return GetUnitState(u, UNIT_STATE_LIFE) * 100 / max_life
            endif
        }
        
        static void SetLifePercent(unit u, real r){
            SetUnitState(u, UNIT_STATE_LIFE, GetMaxLife(u) * RMaxBJ(0, r) * 0.01)
        }
        
        #define GetUnitLifePercent(u) Unit.GetLifePercent(u)
        #define SetUnitLifePercentBJ(u, r) Unit.SetLifePercent(u, r)
        
        /*
        额外移动速度
        */
        static int extraMoveSpeed_count = 0
        static unit extraMoveSpeed_units[]
        static real extraMoveSpeed_speed[]
        static real extraMoveSpeed_x[]
        static real extraMoveSpeed_y[]
        static timer extraMoveSpeed_timer = CreateTimer()
        
        static void ExtraMoveSpeed_Kick(int x){
            //从数组尾部把数据移动过来覆盖
            extraMoveSpeed_units[x] = extraMoveSpeed_units[extraMoveSpeed_count]
            extraMoveSpeed_speed[x] = extraMoveSpeed_speed[extraMoveSpeed_count]
            extraMoveSpeed_x[x]     = extraMoveSpeed_x[extraMoveSpeed_count]
            extraMoveSpeed_y[x]     = extraMoveSpeed_y[extraMoveSpeed_count]
            
            extraMoveSpeed_count --
            
            //如果数组大小为0,则停止计时器
            if extraMoveSpeed_count == 0 then
                PauseTimer(extraMoveSpeed_timer)
            endif
        }
        
        static real ExtraMoveSpeed(unit u, real r){
            int i = 1
            int x = 0
            
            //先检查是否已经在数组中
            loop
                exitwhen i > extraMoveSpeed_count
                if extraMoveSpeed_units[i] == u then
                    x = i
                    i = extraMoveSpeed_count
                elseif GetUnitTypeId(extraMoveSpeed_units[i]) == 0 then
                    ExtraMoveSpeed_Kick(i)
                    i --
                endif
                i ++
            endloop
            
            if x == 0 then
                //不在数组中,新建
                extraMoveSpeed_count ++
                extraMoveSpeed_units[extraMoveSpeed_count] = u
                extraMoveSpeed_speed[extraMoveSpeed_count] = r
                extraMoveSpeed_x[extraMoveSpeed_count]     = GetUnitX(u)
                extraMoveSpeed_y[extraMoveSpeed_count]     = GetUnitY(u)
                
                //如果是数组中第一个单位,则开启计时器
                if extraMoveSpeed_count == 1 then
                    TimerStart(extraMoveSpeed_timer, 0.02, true,\
                        lambda void (){
                            unit u
                            int i = 1
                            loop
                                exitwhen i > extraMoveSpeed_count
                                u = extraMoveSpeed_units[i]
                                real ms = GetUnitMoveSpeed(u)
                                real x  = GetUnitX(u)
                                real y  = GetUnitY(u)
                                real lx = extraMoveSpeed_x[i]
                                real ly = extraMoveSpeed_y[i]
                                real cx = x - lx
                                real cy = y - ly
                                real ds = SquareRoot(cx * cx + cy * cy)
                                real sp = extraMoveSpeed_speed[i]
                                if ms > 10 and ds > ms * 0.018 and ds < ms * 0.022 then
                                    x += cx * sp / ms
                                    y += cy * sp / ms
                                    SetUnitX(u, x)
                                    SetUnitY(u, y)
                                endif
                                extraMoveSpeed_x[i] = x
                                extraMoveSpeed_y[i] = y
                                i ++
                            endloop
                            u = null
                        }\
                    )
                endif
                
                return r
            else
                //在数组中,改变速度
                extraMoveSpeed_speed[x] += r
                
                //若果移动速度变为0,则移出数组
                if extraMoveSpeed_speed[x] == 0 then
                    
                    ExtraMoveSpeed_Kick(x)
                    
                    return 0.
                endif
                
                return extraMoveSpeed_speed[x]
            endif
        }

    endstruct

    private void Init(){
        TimerStart(CreateTimer(), GetRandomInt(30, 60), true, function Unit.RemoveLater_timer)

        Unit.DummySkill_Init()
        Unit.SetHard_Init()
        Unit.initHitDodg()
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library itemLibrary initializer Init needs baseLibrary

    struct Item
        static item it = null

        static void Formula(int id, int id0, int id1, int id2, int id3, int id4, int id5, int id6, int gold){
        }

        static bool UnitHasItemOfTypeBJ2(unit u, int id){
            if id == 0 then
                return false
            endif
            int i = 0
            if GetTriggerEventId() == EVENT_PLAYER_UNIT_DROP_ITEM or GetTriggerEventId() == EVENT_UNIT_DROP_ITEM then
                //如果是在丢弃物品事件中检查,则忽略正在被丢弃的物品
                loop
                    it = UnitItemInSlot(u, i)
                    if GetItemTypeId(it) == id and it != GetManipulatedItem() then
                        return true
                    endif
                    i ++
                    if i > 5 then
                        return false
                    endif
                endloop
            else
                loop
                    if GetItemTypeId(UnitItemInSlot(u, i)) == id then
                        return true
                    endif
                    i ++
                    if i > 5 then
                        return false
                    endif
                endloop
            endif
            return false
        }

        #define UnitHasItemOfTypeBJ(u, id) Item.UnitHasItemOfTypeBJ2(u, id)
        #define YDWEUnitHasItemOfTypeBJNull(u, id) Item.UnitHasItemOfTypeBJ2(u, id)

        static int GetUnitItemCountByType(unit u, int iid){
            int count   = 0
            int i       = 0
            loop
                if GetItemTypeId(UnitItemInSlot(u, i)) == iid then
                    count ++
                endif
                i ++
                exitwhen i > 5
            endloop
            return count
        }
    endstruct

    private void Init(){
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library textLibrary initializer Init needs unitLibrary
    struct text

        /*
        整合漂浮文字
        为(玩家)的(单位)创建漂浮文字(文字内容),(大小),颜色为(红,绿,蓝),(透明度),(移动速度,移动方向),(永久性),在(淡化点)到(消逝)点之间淡化消逝,(可见性)
        可以被"最后创建的漂浮文字"捕捉
        */
        static void CreateText(player p, unit luu, string str, real size, real red, real green, real blue, real see, real speed, real angle, boolean permanent,real fadepoint, real lifespan, integer showTo){
            set bj_lastCreatedTextTag = CreateTextTag()
            call SetTextTagText(bj_lastCreatedTextTag, str, size * 0.023 / 10)
            //call SetTextTagPosUnit(bj_lastCreatedTextTag, luu, 0)
            call SetTextTagPos(bj_lastCreatedTextTag, GetUnitX(luu) - StringLength(str) * 8, GetUnitY(luu), Unit.GetUnitZ(luu) + 100)
            call SetTextTagColor(bj_lastCreatedTextTag, R2I(red * 2.55), R2I(green * 2.55), R2I(blue * 2.55), R2I((100.0 - see) * 2.55))
            call SetTextTagVelocity(bj_lastCreatedTextTag, speed * 0.071 * Cos(angle * bj_DEGTORAD)/ 128, speed * 0.071 * Sin(angle * bj_DEGTORAD)/ 128)
            call SetTextTagPermanent( bj_lastCreatedTextTag, permanent )
            call SetTextTagFadepoint( bj_lastCreatedTextTag, fadepoint )
            call SetTextTagLifespan( bj_lastCreatedTextTag, lifespan )
            if showTo == 1 then
                if IsPlayerEnemy(p, GetLocalPlayer()) then
                    call SetTextTagVisibility(bj_lastCreatedTextTag, false)
                endif
            elseif showTo == 2 then
                if p != GetLocalPlayer() then
                    call SetTextTagVisibility(bj_lastCreatedTextTag, false)
                endif
            endif
        }
    endstruct

    private void Init(){
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library effectLibrary initializer Init needs baseLibrary

    struct Effect
        /*
        创建并删除特效
        自动清除引用点
        */
        static void TempEffect(location where, string modelName, bool b){
            DestroyEffect(AddSpecialEffectLoc(modelName,where))
            if b
                RemoveLocation(where)
            endif
        }

        /*
        新建特效
        */
        static effect AddSpecialEffectLoc2(string s, location loc){
            real x = GetLocationX(loc)
            real y = GetLocationY(loc)
            RemoveLocation(loc)
            return AddSpecialEffect(s, x, y)
        }

        define <Effect.AddSpecialEffectLocMU>(a, b) = Effect.AddSpecialEffectLoc2(b, a)
    endstruct

    private void Init(){
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library soundLibrary initializer Init needs baseLibrary
    struct Sound
        /*
        在 (x,y,z) 播放 (路径名) ,播放速率,是否循环, 是否截断,淡入,淡出,最小衰减范围,最大衰减范围,截断距离
        */
        /*
        private static hashtable HT = InitHashtable()

        static sound play(real x, real y, real z,sound s, real pitch, bool looping, bool stopwhenoutofrange, int fadeInRate, int fadeOutRate, real minDist, real maxDist, real cutoff){
            int k = GetHandleId(s)
            int i = 0
            string name = LoadStr(HT, k, 0)
            real r = GetSoundFileDuration(name) * 0.001
            bj_lastPlayedSound = null
            loop
                exitwhen bj_lastPlayedSound != null
                sound ss = LoadSoundHandle(HT, k, i)
                if ss == null
                    bj_lastPlayedSound = CreateSou##nd(name, looping, true, stopwhenoutofrange, fadeInRate, fadeOutRate, "")
                    SaveSoundHandle(HT, k, i, bj_lastPlayedSound)
                elseif sys.getTime() > LoadReal(HT, k, i)
                    bj_lastPlayedSound = ss
                endif
                i++
            endloop
            SaveReal(HT, k, i-1, sys.getTime() + r)
            SetSoundPosition(bj_lastPlayedSound, x, y, z)
            SetSoundPitch(bj_lastPlayedSound, pitch)
            SetSoundDistances(bj_lastPlayedSound, minDist, maxDist)
            SetSoundDistanceCutoff(bj_lastPlayedSound, cutoff)
            StartSound(bj_lastPlayedSound)
            return bj_lastPlayedSound
        }

        static sound SaveSound(string filename, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting){
            bj_lastPlayedSound = CreateSou##nd(filename, looping, is3D, stopwhenoutofrange, fadeInRate, fadeOutRate, eaxSetting)
            int k = GetHandleId(bj_lastPlayedSound)
            SaveStr(HT,k,0,filename)
            StartSound(bj_lastPlayedSound)
            StopSound(bj_lastPlayedSound, false, false)
            return bj_lastPlayedSound
        }

        */

        static sound CreateSound2(string filename, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting){
            bj_lastPlayedSound = Create##Sound(filename, looping, is3D, stopwhenoutofrange, fadeInRate, fadeOutRate, eaxSetting)
            SetSoundPosition(bj_lastPlayedSound, 0, 0, 0)
            StartSound(bj_lastPlayedSound)
            KillSoundWhenDone(bj_lastPlayedSound)
            return Create##Sound(filename, looping, is3D, stopwhenoutofrange, fadeInRate, fadeOutRate, eaxSetting)
        }

        //define CreateSound = Sound.CreateSound2

        static void SetSoundVolume2(sound s, int i){
            if i > 0 then
                SetSoundVolume(s, i)
            else
                SetSoundVolume(s, 0)
            endif
        }

        #define SetSoundVolume(s, i) Sound.SetSoundVolume2(s, i)

        static void PlaySoundAtPointBJ2(sound soundHandle, real volumePercent, location loc, real z){
            SetSoundPosition(soundHandle, GetLocationX(loc), GetLocationY(loc), z + GetLocationZ(loc))
            SetSoundVolume(soundHandle, PercentToInt(volumePercent, 127))
            PlaySoundBJ(soundHandle)
            RemoveLocation(loc)
        }

        static sound ss[]
        static int si[]
        static int s_count = 0
        static timer s_timer = CreateTimer()

        static void KillSound(sound s){
            s_count ++
            ss[s_count] = s
            si[s_count] = 2
        }
        
        static void KillSound_Init(){
            TimerStart(CreateTimer(), 60, true,\
                lambda void(){
                    int x = 1
                    loop
                        exitwhen x > s_count
                        si[x] --
                        if si[x] == 0 then
                            KillSoundWhenDone(ss[x])
                            //从队列尾部拉个过来
                            loop
                                si[s_count] --
                                if si[s_count] == 0 then
                                    KillSoundWhenDone(ss[s_count])
                                    s_count --
                                    exitwhen s_count == 0
                                else
                                    si[x] = si[s_count]
                                    ss[x] = ss[s_count]
                                    s_count --
                                    exitwhen true
                                endif 
                            endloop
                        endif
                        x ++
                    endloop
                }\
            )
        }

        <?
            update('war3map.j', '音效预处理',
                function(content)

                    local InitSounds = content:match 'function InitSounds takes nothing returns nothing(.-)endfunction' .. '__end'
                    local sounds = {}

                    InitSounds = InitSounds:gsub('set', '__endset')

                    for v_name, texts in InitSounds:gmatch 'set ([%w_]+)(.-)__end' do
                        sounds[v_name] = texts:gsub('CreateSound', 'Create##Sound')
                        table.insert(sounds, v_name)
                    end

                    content = content:gsub('(StopSound%C+%c+%C+)PlaySound', '%1Play##Sound')

                    content = content:gsub('([%s%.]PlaySound%w+%( )([%w_]+)(%C+)',
                        function(t1, v_name, t2)
                            local r = ('%s%s%s\ncall Sound.KillSound(%s)\nset %s%s'):format(t1, v_name, t2, v_name, v_name, sounds[v_name])
                            --error(r)
                            return r
                        end
                    )

                    --[=[
                    local codes = {}
                    for i, v_name in ipairs(sounds) do
                        codes[i] = ([[
                            SetSoundPosition(%s, x, y, 0)
                            SetSoundVolume(%s, 0)
                            StartSound(%s)
                        ]]):format(v_name, v_name, v_name)
                    end
                    content = content:gsub('__START_ALL_SOUNDS__', table.concat(codes, '\n'))
                    --]=]

                    return content
                end
            )
        ?>
        
        /*
        单位回应
        */
        private static int guid
        private static int grestype
        private static string gfiles
        
        static void InitUnitResponses_Execute(){
            int key
            if grestype == 1 then
                key = StringHash("选中回应")
            elseif grestype == 2 then
                key = StringHash("移动回应")
            elseif grestype == 3 then
                key = StringHash("攻击回应")
            endif
            
            int count = String.Split(gfiles, ";")
            SaveInteger(YDHT, guid, key, count)
            
            sound snd
            
            int i = 1
            loop
                exitwhen i > count
                SaveStr(YDHT, guid, key + i, String.GetStr(i))
                
                //预播放
                snd = CreateSound(String.GetStr(i), false, false, false, 10, 10, "HeroAcksEAX")
                SetSoundVolume(snd, 0)
                StartSound(snd)
                KillSoundWhenDone(snd)
                i ++
            endloop
            
            snd = null
        }
        
        static void InitUnitResponses(int uid, int restype, string files){
            guid = uid
            grestype = restype
            gfiles = files
            
            trigger trg = CreateTrigger()
            TriggerAddAction(trg, function Sound.InitUnitResponses_Execute)
            TriggerExecute(trg)
            DestroyTrigger(trg)
            trg = null
        }
        
        static real last_UnitResponseTime[]
        
        static void PlayUnitResponses(int key){
            int i = GetPlayerId(GetTriggerPlayer())
            int uid = GetUnitTypeId(GetTriggerUnit())
            
            //音效数量
            int count = LoadInteger(YDHT, uid, key)
            if count == 0 then
                return
            endif
            
            //按顺序取出一个音效
            int index = LoadInteger(YDHT, key, i) + 1
            if index > count then
                index = 1
            endif
            SaveInteger(YDHT, key, i, index)
            
            string file = LoadStr(YDHT, uid, key + index)
            
            //创建音效
            sound snd = CreateSound(file, false, false, false, 10, 10, "HeroAcksEAX")
            if Player(i) == GetLocalPlayer() then
                StartSound(snd)
            endif
            
            //记录播放时间
            last_UnitResponseTime[i] = sys.getTime() + GetSoundDuration(snd) * 0.001
            
            //音效回收
            KillSound(snd)
            
            snd = null
        }
        
        static void UnitResponses_Init(){
            trigger trg = CreateTrigger()
            
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SELECTED)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
            TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
            
            TriggerAddCondition(trg, Condition(\
                lambda void(){
                    int i = GetPlayerId(GetTriggerPlayer())
                    
                    //上次的单位回应是否还在播放   
                    if sys.getTime() < last_UnitResponseTime[i] + 10 then
                    
                        return    

                    endif
                    
                    if GetTriggerEventId() == EVENT_PLAYER_UNIT_SELECTED then
                        //选中回应
                        if GetOwningPlayer(GetTriggerUnit()) == Player(15) or GetOwningPlayer(GetTriggerUnit()) == GetTriggerPlayer() then
                            //选中中立英雄(选人区)或自己的英雄才会有回应
                            PlayUnitResponses(StringHash("选中回应"))
                        endif
                    elseif not Unit.IsOrderedByScript then
                        //指令不是由触发器发布的
                        int order = GetIssuedOrderId()
                        if order == OrderId("move") then
                            PlayUnitResponses(StringHash("移动回应"))
                        elseif order == OrderId("attack") then
                            PlayUnitResponses(StringHash("攻击回应"))
                        elseif order == OrderId("smart") then
                            //右键点击
                            if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER and IsUnitEnemy(GetOrderTargetUnit(), GetTriggerPlayer()) then
                                PlayUnitResponses(StringHash("攻击回应"))
                            else
                                PlayUnitResponses(StringHash("移动回应"))
                            endif
                        endif
                    endif
                }\
            ))
            
            trg = null
        }

    endstruct

    private void Init(){
        /*
        TimerStart(CreateTimer(), 0, false,\
            lambda void (){
                DestroyTimer(GetExpiredTimer())
                real x = GetCameraTargetPositionX(), y = GetCameraTargetPositionY()
                __START_ALL_SOUNDS__
            }\
        )
        */
        Sound.KillSound_Init()
        Sound.UnitResponses_Init()
    }
endlibrary
########
########
//TESH.scrollpos=302
//TESH.alwaysfold=0
library testLibrary initializer Init needs baseLibrary, processLibrary
    struct test
        static trigger testTrigger = CreateTrigger()
        static bool Enable  = false

        static bool action(){
            string s = GetEventPlayerChatString()
            player p = GetTriggerPlayer()
debug@      if p != Play##er(0) and not test.Enable then
debug@          DisplayTimedTextToPlayer(p, 0, 0, 10, "1楼关闭了测试指令,若需启用请1楼输入 .test")
debug@          p = null
debug@          return false
debug@      endif
            int id = GetPlayerId(p)
            unit hero = udg_player[id + 1]
            String.Split(s, " ")
            s = String.GetStr(1)
            s = StringCase(s, false)
            if s == ".lv" then
                SetHeroLevel(hero, S2I(String.GetStr(2)), true)
            elseif s == ".showid" then
                int i = 0
                BJDebugMsg("[当前ID]" + I2S(GetPlayerId(GetLocalPlayer())) + " / " + I2S(GetHandleId(GetLocalPlayer())))
                loop
                    exitwhen i > 9
                    BJDebugMsg("[" + I2S(i) + ":" + GetPlayerName(Player(i)) + "] → " + I2S(GetPlayerId(Player(i))) + " / " + I2S(GetHandleId(Player(i))))
                    i ++
                endloop
            elseif s == ".hp" then
                SetUnitState(hero, UNIT_STATE_LIFE, 999999)
                SetUnitState(hero, UNIT_STATE_MANA, 999999)
                UnitResetCooldown(hero)
            elseif s == ".move" then
                if sys.selfp == p then
                    StoreInteger(sys.GC, "mx", I2S(id), R2I(GetCameraTargetPositionX()))
                    StoreInteger(sys.GC, "my", I2S(id), R2I(GetCameraTargetPositionY()))
                    SyncStoredInteger(sys.GC, "mx", I2S(id))
                    SyncStoredInteger(sys.GC, "my", I2S(id))
                endif
                StoreInteger(sys.GC, "mx", I2S(id), 0)
                StoreInteger(sys.GC, "my", I2S(id), 0)
                TriggerSleepAction(1)
                real x = GetStoredInteger(sys.GC, "mx", I2S(id))
                real y = GetStoredInteger(sys.GC, "my", I2S(id))
                SetUnitX(hero, x)
                SetUnitY(hero, y)
            elseif s == ".gold" then
                SetPlayerStateBJ(p, PLAYER_STATE_RESOURCE_GOLD, 999999999)
            elseif s == ".skill" then
                int sid = YDWES2Id(String.GetStr(2))
                int lv = S2I(String.GetStr(3))
                if GetUnitAbilityLevel(hero, sid) == 0 then
                    UnitAddAbility(hero, sid)
                    SetUnitAbilityLevel(hero, sid, lv)
                    UnitMakeAbilityPermanent(hero, true, sid)
                else
                    if lv == 0 then
                        UnitRemoveAbility(hero, sid)
                    else
                        SetUnitAbilityLevel(hero, sid, lv)
                    endif
                endif
            elseif s == ".pskill" then
                hero = udg_Pet[GetPlayerId(p) + 1]
                int sid = YDWES2Id(String.GetStr(2))
                int lv = S2I(String.GetStr(3))
                if GetUnitAbilityLevel(hero, sid) == 0 then
                    UnitAddAbility(hero, sid)
                    SetUnitAbilityLevel(hero, sid, lv)
                    UnitMakeAbilityPermanent(hero, true, sid)
                else
                    if lv == 0 then
                        UnitRemoveAbility(hero, sid)
                    else
                        SetUnitAbilityLevel(hero, sid, lv)
                    endif
                endif
            elseif s == ".handle" then
                int i = 1
                location loc[]
                loop
                    exitwhen i > 10
                    loc[i] = Location(0, 0)
                    BJDebugMsg("<句柄泄露测试>" + I2S(GetHandleId(loc[i])))
                    i ++
                endloop
                i = 1
                loop
                    exitwhen i > 10
                    RemoveLocation(loc[i])
                    loc[i] = null
                    i ++
                endloop
            elseif s == ".key" then
                if check_timer < 1000 then
                    int key = S2I(String.GetStr(2))
                    int hash = StringHash("2.6H" + sPlayer.GetPlayerBaseName(p) + "呜喵")
                    if key == hash then
                        check_timer = 99999
                        BJDebugMsg("|cffff8888授权码已确认,感谢参与测试,你们的支持是地图发展的动力!|r")
                        BJDebugMsg("|cffff8888本地图保存于<?=os.date('[%Y/%m/%d - %H:%M:%S]')?>,请注意确认版本")
                    endif
                endif
            elseif s == ".ai" then
                AI.Init()
            elseif s == ".mh" then
                unit smd = udg_SmD[id + 1]
                UnitRemoveAbility(smd, 'A0C1')
                UnitAddAbility(smd, 'A0BJ')
                SetUnitAbilityLevel(smd, 'A0BJ', udg_zhengshu2[179] )
                smd = null
            elseif s == ".aid" then
                SetUnitAnimationByIndex(hero, S2I(String.GetStr(2)))
            elseif s == ".neverdead" then
                SaveInteger(YDHT, GetHandleId(hero), StringHash("免疫死亡"), S2I(String.GetStr(2)))
            elseif s == ".damage" then
                UnitDamageTarget(hero, hero, S2R(String.GetStr(2)), false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
            elseif s == ".hard" then
                Unit.SetHard(hero, S2R(String.GetStr(2)))
            elseif s == ".getdef" then
                BJDebugMsg(R2S(Unit.GetUnitDefence(hero)))
            elseif s == ".test" then
                if p == Play##er(0) then
                    test.Enable = not test.Enable
                    if test.Enable then
                        BJDebugMsg("测试指令已开启")
                    else
                        BJDebugMsg("测试指令已关闭")
                    endif
                endif
            elseif s == ".dummy" then
                unit u = CreateUnit(Player(12), 'n02H', GetUnitX(hero), GetUnitY(hero), 0)
                int hp = S2I(String.GetStr(2))
                if hp > 0 then
                    YDWEGeneralBounsSystemUnitSetBonus(u, 0, 2, hp )
                endif
                if String.GetStr(3) == "false" then
                    UnitAddAbility(u, 'Abun')
                endif
                u = null
            elseif s == ".pause" then
                if LoadBoolean(YDHT, GetHandleId(hero), StringHash("暂停:测试")) then
                    Unit.PauseUnitMU(hero, false, "测试")
                else
                    Unit.PauseUnitMU(hero, true, "测试")
                endif
            elseif s == ".gamespeed" then
                SetGameSpeed(ConvertGameSpeed(S2I(String.GetStr(2))))
            elseif s == ".addcrit" then
                Unit.Crit(hero, true, S2R(String.GetStr(2)), S2R(String.GetStr(3)), "测试", 0)
            elseif s == ".removecrit" then
                Unit.Crit(hero, false, S2R(String.GetStr(2)), S2R(String.GetStr(3)), "测试", 0)
            elseif s == ".addhitdodg" then
                Unit.HitDodg(hero, true, S2R(String.GetStr(2)), "测试", S2I(String.GetStr(3)))
            elseif s == ".removehitdodg" then
                Unit.HitDodg(hero, false, S2R(String.GetStr(2)), "测试", S2I(String.GetStr(3)))
            elseif s == ".leak" then
                GetLocalizedHotkey("yd_leak_monitor::create_report")
            elseif s == ".getherodataint" then
                BJDebugMsg(String.GetStr(2) + "→" + I2S(LoadInteger(YDHT, GetHandleId(hero), StringHash(String.GetStr(2)))))
            elseif s == ".getherodatareal" then
                BJDebugMsg(String.GetStr(2) + "→" + R2S(LoadReal(YDHT, GetHandleId(hero), StringHash(String.GetStr(2)))))
            elseif s == ".cover" then
                int key = process.Create(hero, "全部", 1000000, true)
                process.Remove(key)
            else
                p = null
                hero = null
                return false
            endif
            BJDebugMsg(GetPlayerName(p) + "使用了测试指令:" + GetEventPlayerChatString())
            p = null
            hero = null
            return false
        }

        static int check_timer = 60

        static void check_func1(){
            if check_timer > 1000 then
                DestroyTimer(GetExpiredTimer())
                return
            endif
            if check_timer > 0 then
                BJDebugMsg("|cffff8888本地图为测试版地图,请输入授权码,否则游戏将在 " + I2S(check_timer) + " 秒后结束|r")
                check_timer -= 10
            else
                BJDebugMsg("|cffff8888测试地图未授权!!!|r")
                PauseAllUnitsBJ(true)
            endif
        }

        static void check(){
            return
            if bj_isSinglePlayer then
                return
            endif
            check_func1()
            TimerStart(CreateTimer(), 10, true, function test.check_func1)
        }

        //重载计时器
        //双向链表结构
        static int      timer_last[]        //上一个索引
        static int      timer_next[]        //下一个索引
        static timer    timer_timer[]       //计时器
        static real     timer_dur[]         //计时器周期
        static real     timer_start_time[]  //计时器启动的时间
        static string   timer_v_name[]      //计时器变量名
        static string   timer_f_name[]      //计时器所在函数名

        static int      timer_idle[]          //空闲索引
        static int      timer_idle_top = 8191   //空闲索引计数

        static void RemoveTimer(timer t){
            int key = LoadInteger(YDHT, StringHash("计时器重载索引"), GetHandleId(t))
            if key == 0 then
                return
            endif
            //将key放回空闲索引
            timer_idle[++ timer_idle_top] = key

            //断开链表
            int last    = timer_last[key]
            int next    = timer_next[key]
            timer_next[last]    = next
            timer_last[next]    = last

            timer_timer[key]    = null

            //清除保存的key
            RemoveSavedInteger(YDHT, StringHash("计时器重载索引"), GetHandleId(t))
        }

        static void Hook_TimerStart(timer t, real r, bool b, code c, string v_name, string f_name){
            TimerStart(t, r, b, c)
            RemoveTimer(t)
            if r > 5 or not b then
                return
            endif

            //取出一个空闲索引
            int key = timer_idle[timer_idle_top --]
            if key == 0 then
                BJDebugMsg("<错误>计时器索引被用完!")
                Lua_hook(sys.selfp, "hook_timer_error")
                return
            endif
            //索引0是保留的,通过索引0访问第一个和最后一个索引
            //int first   = timer_next[0]
            int last    = timer_last[0]
            //自己成为新的最后一个
            timer_last[0]       = key
            timer_next[key]     = 0
            timer_next[last]    = key
            timer_last[key]     = last
            //开始保存数据
            timer_timer[key]    = t
            timer_dur[key]      = r
            timer_start_time[key]   = sys.getTime()
            timer_v_name[key]   = v_name
            timer_f_name[key]   = f_name
            //保存key
            SaveInteger(YDHT, StringHash("计时器重载索引"), GetHandleId(t), key)
        }

        static void Hook_StartTimerBJ(timer t, bool b, real r, string v_name, string f_name){
            bj_lastStartedTimer = t
            Hook_TimerStart(t, r, b, null, v_name, f_name)
        }

        static void Hook_PauseTimer(timer t){
            RemoveTimer(t)
            PauseTimer(t)
        }

        static void Hook_DestroyTimer(timer t){
            RemoveTimer(t)
            DestroyTimer(t)
        }

        static void TimerInit(){
            int i = 0
            loop
                exitwhen i > timer_idle_top
                timer_idle[++ i] = timer_idle_top - i + 1
            endloop

            //循环遍历所有计时器,检查循环时间太长的
            TimerStart(CreateTimer(), 60, true,\
                lambda void (){
                    int key     = 0
                    real time   = sys.getTime()
                    loop
                        key = timer_next[key]
                        exitwhen key == 0
                        real dur    = time - timer_start_time[key]
                        int times   = R2I(dur / timer_dur[key])
                        if times > 1000 and dur > 300 then
                            BJDebugMsg("<警告>计时器 [" + timer_v_name[key] + "] 循环时间超过300秒,已被忽略!!启动函数 [" + timer_f_name[key] + "]")
                            Lua_hook(sys.selfp, "hook_timer_ignore " + I2S(key))
                            RemoveTimer(timer_timer[key])
                        endif
                    endloop
                }\
            )
        }

        #ifndef RELEASE
            #define TimerStart(t, r, b, c) test.Hook_TimerStart(t, r, b, c, `t`, `FUNCNAME`)
            #define StartTimerBJ(t, b, r) test.Hook_StartTimerBJ(t, b, r, `t`, `FUNCNAME`)
            #define PauseTimer(t) test.Hook_PauseTimer(t)
            #define DestroyTimer(t) test.Hook_DestroyTimer(t)

        #endif
        
        #ifndef RELEASE
        
            static location temp_Loc
            
            static location PolarProjectionBJ2(location source, real dist, real angle, string func_name){
                real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
                real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
                temp_Loc = Location(x, y)
                //发送给lua:点,函数名
                Lua_hook(sys.selfp, "debug_PolarProjection " + I2S(GetHandleId(temp_Loc)) + " " + func_name)
                return temp_Loc
            }

            #define PolarProjectionBJ(l, d, a) test.PolarProjectionBJ2(l, d, a, `FUNCNAME`)
        
        #endif
        
    endstruct

    private void Init(){
        int i = 0
        loop
            exitwhen i > 11
            debug@ TriggerRegisterPlayerChatEvent(test.testTrigger, Player(i), "", false)
            i ++
        endloop
        TriggerAddAction(test.testTrigger, function test.action)

        debug@ test.check()
        debug@ test.TimerInit()
    }
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library processLibrary initializer Init needs baseLibrary
    struct process
		//双向链表
			//结构
			static int keys[]
			static unit us[]
			static string name[]
			static int uper[]
			static bool cover[]
			static bool enable[]
            static trigger trg[]
			//节点
			static int lastkey[]
			static int nextkey[]
			//指向hash序列
			static int hashindex[]

		//哈希
			//索引常量
			static int h_count = 0
			static int h_index[]
			static int h_max = 0

		//函数
			//剔除 单位 优先级小于等于 100 的 名字 过程
			//返回int 剩余过程数量
			static int Cover(unit u, int uper, string name){
				int h = GetHandleId(u)
				int count = 0
				int max = LoadInteger(YDHT, h, h_max)
                int new_max = 0
				int i = 1
                //BJDebugMsg(I2S(max))
                Event.index ++
                SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "过程被剔除")
				loop
					exitwhen i > max
					int key = LoadInteger(YDHT, h, h_index[i])
					if key != 0 then
                        new_max = i
						if (name == "全部" or .name[key] == name) and uper >= .uper[key] and enable[key] then
                            //debug@ BJDebugMsg("<优先级被剔除> unit:[" + GetUnitName(u) + "] process:[" + .name[key] + "] hashindex:[" + I2S(i) + "] key:[" + I2S(key) + "]")
							enable[key] = false
							SaveInteger(YDHT, h, h_index[i], 0)
                            if trg[key] != null then
                                if TriggerEvaluate(trg[key]) then
                                    TriggerExecute(trg[key])
                                endif
                                FlushChildHashtable(YDHT, GetHandleId(trg[key]))
                                DestroyTrigger(trg[key])
                            endif
						else
                            count ++
						endif
					endif
					i ++
				endloop
                SaveStr(YDHT, StringHash("事件返回"), StringHash("名称"), "")
                Event.index --
                SaveInteger(YDHT, h, h_max, new_max)
                SaveInteger(YDHT, h, h_count, count)
				return count
			}

			//新建 单位 的 名字 过程, 优先级为 100 ,剔除低优先级过程 true
			//返回int key
			static int Create(unit u, string name, int uper, bool cover){
                int key
				//检查是否有更高优先级存在
				int h = GetHandleId(u)
                if h == 0 then
                    BJDebugMsg("<过程目标不存在!>请截图汇报")
                    BJDebugMsg("<名称>" + name)
                    BJDebugMsg("<优先级>" + I2S(uper))
                endif
				int max = LoadInteger(YDHT, h, h_max)
				int i = 1
				loop
					exitwhen i > max
					key = LoadInteger(YDHT, h, h_index[i])
					if key != 0 and .name[key] == name and .uper[key] > uper and .cover[key] and enable[key] then
                        //debug@ BJDebugMsg("<有更高优先级存在> unit:[" + GetUnitName(u) + "] process:[" + name + "] hashindex:[" + I2S(i) + "] key:[" + I2S(key) + "]")
						return 0
					endif
					i ++
				endloop
				//剔除低优先级过程
				if cover then
					Cover(u, uper, name)
				endif
				//过程计数
				int count = LoadInteger(YDHT, h, h_count) + 1
                SaveInteger(YDHT, h, h_count, count)
				max = LoadInteger(YDHT, h, h_max)
				if count > max then
					max = count
					SaveInteger(YDHT, h, h_max, max)
				endif
				//创建一个key
				key = 1
				loop
					exitwhen hashindex[key] == 0
					key ++
				endloop
				us[key] = u
				.name[key] = name
				.uper[key] = uper
				.cover[key] = cover
                trg[key] = null
				enable[key] = true
				//在hash里找一个空位插进去
				i = 1
				loop
					exitwhen LoadInteger(YDHT, h, h_index[i]) == 0
					i ++
				endloop
				if i > 100 then
					BJDebugMsg("<未找到空闲过程位> unit:[" + GetUnitName(u) + "] process:[" + name + "] uper:[" + I2S(uper) + "]")
					return 0
				endif
				SaveInteger(YDHT, h, h_index[i], key)
				hashindex[key] = i
				//链接链表
				lastkey[key] = 0
				nextkey[key] = nextkey[0]
				nextkey[0] = key
                //debug@ BJDebugMsg("<新建过程> unit:[" + GetUnitName(u) + "] process:[" + name + "] hashindex:[" + I2S(i) + "] key:[" + I2S(key) + "]")
				return key
			}

            static int lastKey

            define <process.Create2>(a, b, c, d) = {process.lastKey = process.Create(a, b, c, d)}

			//过程 #key 有效
			//返回bool 是否有效
			static bool IsEnable(int key){
				return enable[key]
			}

			//结束过程 #key
			//返回bool 是否有效
			static bool Remove(int key){
                if key == 0 then
                    return false
                endif
				if hashindex[key] == 0 then
                    BJDebugMsg("<试图结束不存在的过程!请截图汇报!>")
                    BJDebugMsg("unit:[" + GetUnitName(us[key]) + "] process:[" + name[key] + "] hashindex:[" + I2S(hashindex[key]) + "] key:[" + I2S(key) + "]")
					return false
				endif
				int h = GetHandleId(us[key])
                if enable[key] then
                    enable[key] = false
                    SaveInteger(YDHT, h, h_index[hashindex[key]], 0)
                endif
                //debug@ BJDebugMsg("<结束过程> unit:[" + GetUnitName(us[key]) + "] process:[" + name[key] + "] hashindex:[" + I2S(hashindex[key]) + "] key:[" + I2S(key) + "]")
				hashindex[key] = 0
				int last = lastkey[key]
				int next = nextkey[key]
				nextkey[last] = next
				lastkey[next] = last
				return true
			}

            //设置过程优先级
            static void SetUper(int key, int uper){
                .uper[key] = uper
            }

            //单位是否拥有某过程
            static bool HasName(unit u, int uper, string name, bool cover_flag, bool enable_flag){
                int key
				int h = GetHandleId(u)
				int max = LoadInteger(YDHT, h, h_max)
				int i = 1
				loop
					exitwhen i > max
					key = LoadInteger(YDHT, h, h_index[i])
					if key != 0 and .name[key] == name and .uper[key] > uper and (.cover[key] or cover_flag) and (enable[key] or enable_flag) then
						return true
					endif
					i ++
				endloop
                return false
            }
	endstruct

	private void Init(){
		int i = 1
		loop
			exitwhen i > 100
			process.h_index[i] = StringHash("过程" + I2S(i))
			i ++
		endloop
        process.h_count = StringHash("过程数量")
        process.h_max = StringHash("过程最大值")
	}
endlibrary
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library moverLibrary initializer Init needs baseLibrary

    struct Mover
        /*
        设为弹幕
        */
        debug@ static group Mover_debug_group = CreateGroup()

        static void SetMover(unit u){
            real x = GetUnitX(u)
            real y = GetUnitY(u)
            SetUnitPosition(u, x, y)
            //因为绑了数据,所以加入清理组待清理
            FlushUnit_Add(u)

            release@ return
            //检查移动速度
            if GetUnitMoveSpeed(u) == 0 then
                BJDebugMsg("<弹幕>[" + GetUnitName(u) + "]的移动速度不能为0!")
            endif
            if GetUnitAbilityLevel(u, 'Aloc') == 0 then
                BJDebugMsg("<弹幕>[" + GetUnitName(u) + "]必须有蝗虫技能!")
            endif
            if not IsUnitType(u, UNIT_TYPE_ANCIENT) then
                BJDebugMsg("<弹幕>[" + GetUnitName(u) + "]必须有古树类型!")
            endif
            if not IsUnitType(u, UNIT_TYPE_TAUREN) then
                BJDebugMsg("<弹幕>[" + GetUnitName(u) + "]必须有牛头人类型!")
            endif
debug@      GroupEnumUnitsInRange(Mover_debug_group, x, y, 0, null)
debug@      if not IsUnitInGroup(u, Mover_debug_group) then
debug@          BJDebugMsg("<弹幕>[" + GetUnitName(u) + "]选取测试失败!请确认物编中是否有守卫类型!")
debug@      endif
        }

        static void SetStateReal(unit u, int state, real r){
            if state == 1 then
                //在原力场中降低的移动速度
                SaveReal(YDHT, GetHandleId(u), StringHash("原力场-移速降低"), r)
            elseif state == 2 then
                //在原力场中受到的额外斥力
                SaveReal(YDHT, GetHandleId(u), StringHash("原力场-额外斥力"), r)
            endif
        }
    endstruct

    private void Init(){
    }
endlibrary
########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
#define SetMapDescription(s) SetMapDescription(s) YDNL call PlayMusic("LoadingMusic.mp3")
########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AIlibrary initializer Init needs baseLibrary

    void Debug(string s){
        BJDebugMsg("<AI.Debug>"+s)
    }

    //AI结构体
    struct AI

        //哈希表
        private static hashtable HT = InitHashtable()

        //哈希表索引
        private static int STRUCT = 1

        //注册英雄类型
        static int typeCount = 38 //英雄类型数量
        static int type[] //英雄类型ID
        static void initType() //注册英雄类型,在全局变量 Hero 设置后调用
        {
            int i = 1
            loop
                exitwhen i > typeCount
                type[i] = GetUnitTypeId(udg_hero[i])
                i++
            endloop
        }

        //是否是第一次启动AI
        static bool first = true

        //AI设置
        real homeX
        real homeY

        void setHomePoint(real x, real y) //设置AI的家的坐标,用于保护基地
        {
            homeX = x
            homeY = y
        }

        real restX
        real restY

        void setRestPoint(real x, real y) //设置AI的休息坐标,用于温泉边回血
        {
            restX = x
            restY = y
        }

        unit home
        void setHome(unit u) //设置AI的基地
        {
            home = u
        }

        real wayPointX[10]
        real wayPointY[10]
        void setWayPoint(int i, real x, real y) //设置AI的分路路径点.1=上路,2=下路,3=打野
        {
            if i > 10
                Debug("路径点编号不能大于10")
                return
            endif
            wayPointX[i] = x
            wayPointY[i] = y
        }

        //创建AI
        unit who //对应的英雄
        int id //英雄的单位类型[1-38]

        static AI create(unit u) //注册AI
        {
            int this = AI.allocate() //创建结构体
            who = u
            player p = GetOwningPlayer(u)
            int tid = GetPlayerTeam(p)

            if first //如果是首次开启AI,那么注册物编数据
                first = false
                //object.saveData()
            endif

            //注册一些数据
            if tid == 0 //万物复苏方
                setHomePoint(-5437, -6336)
                setRestPoint(-6543, -6776)
                setHome(gg_unit_hcas_0015)
            elseif tid == 1 //极冻酷寒
                setHomePoint(5575, 5720)
                setRestPoint(6233, 6262)
                setHome(gg_unit_e05G_0101)
            endif

            SaveInteger(HT, STRUCT, H2I(u), this) //将结构体索引保存在哈希表中,这样可以通过英雄来找到AI

            //找到该英雄的编号
            int i = 1
            loop
                exitwhen i > typeCount
                if GetUnitTypeId(u) == type[i]
                    id = i
                    exitwhen true
                endif
                i++
            endloop

            debug@ Debug("AI注册成功,英雄编号为"+I2S(id)+",AI索引为"+I2S(this))
            p = null
            return this
        }

        static AI get(unit u) //根据英雄找到该英雄的AI
        {
            return LoadInteger(HT, STRUCT, H2I(u))
        }

        void destroy() //移除AI
        {
            RemoveSavedInteger(HT, STRUCT, H2I(who)) //将结构体索引从哈希表中删除
            deallocate() //摧毁结构体
        }

        static void check_AI(){
            bool flag = true
            int i = 0
            loop
                exitwhen i > 9
                if GetPlayerController(Player(i)) == MAP_CONTROL_COMPUTER and (udg_player[i + 1] == null or get(udg_player[i + 1]) == 0) then
                    flag = false
                    if udg_player[i + 1] != null then
                        AI.create(udg_player[i + 1])
                    endif
                endif
                i ++
            endloop
            if flag then
                DestroyTimer(GetExpiredTimer())
                debug@ Debug("启用AI")
            endif
        }

        static void Init(){
            debug@ Debug("开启AI")
            TimerStart(CreateTimer(), 3, true, function AI.check_AI)
        }

    endstruct

    private void Init(){
    }
endlibrary
########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########
//TESH.scrollpos=121
//TESH.alwaysfold=0
function Trig_________________pifchushihuaActions takes nothing returns nothing


    set udg_pf[1] = 'A0U8'
    set udg_pf[2] = 'A0S9'
    set udg_pf[3] = 'A0WV'
    set udg_pf[4] = 'A0WY'
    set udg_pf[5] = 'A0TT'
    set udg_pf[6] = 'A0UB'
    set udg_pf[7] = 'A10I'
    set udg_pf[8] = 'A0VU'
    set udg_pf[9] = 'A0VV'
    set udg_pf[10] = 'A10J'
    set udg_pf[11] = 'A12Y'
    set udg_pf[12] = 'A10M'
    set udg_pf[13] = 'A0VZ'
    set udg_pf[14] = 'A0VC'
    set udg_pf[15] = 'A10N'
    set udg_pf[16] = 'A12W'
    set udg_pf[17] = 'A0UX'
    set udg_pf[18] = 'A10P'
    set udg_pf[19] = 'A0V3'
    set udg_pf[20] = 'A0X4'
    set udg_pf[21] = 'A0UV'
    set udg_pf[22] = 'A0UY'
    set udg_pf[23] = 'A0TU'
    set udg_pf[24] = 'A10Q'
    set udg_pf[25] = 'A10S'
    set udg_pf[26] = 'A0UU'
    set udg_pf[27] = 'A0UA'
    set udg_pf[28] = 'A136'
    set udg_pf[29] = 'A10T'
    set udg_pf[30] = 'A130'
    set udg_pf[31] = 'A0XD'
    set udg_pf[32] = 'A10V'
    set udg_pf[33] = 'A10W'
    set udg_pf[34] = 'A10X'
    set udg_pf[35] = 'A10Y'
    set udg_pf[36] = 'A0VW'
    set udg_pf[37] = 'A10Z'
    set udg_pf[38] = 'A0U5'
    set udg_pf[39] = 'A110'
    set udg_pf[40] = 'A112'
    set udg_pf[41] = 'A111'
    set udg_pf[42] = 'A113'
    set udg_pf[43] = 'A0VY'
    set udg_pf[44] = 'A0X3'
    set udg_pf[45] = 'A0UZ'
    set udg_pf[46] = 'A0V4'
    set udg_pf[47] = 'A0V5'
    set udg_pf[48] = 'A115'
    set udg_pf[49] = 'A0V1'
    set udg_pf[50] = 'A114'
    set udg_pf[51] = 'A116'
    set udg_pf[52] = 'A0TV'
    set udg_pf[53] = 'A155'
    set udg_pf[54] = 'A117'
    set udg_pf[55] = 'A11I'
    set udg_pf[56] = 'A118'
    set udg_pf[57] = 'A0VX'
    set udg_pf[58] = 'A119'
    set udg_pf[59] = 'A11A'
    set udg_pf[60] = 'A0V2'
    set udg_pf[61] = 'A0X5'
    set udg_pf[62] = 'A0V0'
    set udg_pf[63] = 'A11D'
    set udg_pf[64] = 'A0U6'
    set udg_pf[65] = 'A11H'
    set udg_pf[66] = 'A0TZ'
    set udg_pf[67] = 'A0U1'
    set udg_pf[68] = 'A11J'
    set udg_pf[69] = 'A11L'
    set udg_pf[70] = 'A11M'
    set udg_pf[71] = 'A132'
    set udg_pf[72] = 'A11P'
    set udg_pf[73] = 'A0VF'
    set udg_pf[74] = 'A0UI'
    set udg_pf[75] = 'A12S'
    set udg_pf[76] = 'A135'
    set udg_pf[77] = 'A13D'
    set udg_pf[78] = 'A133'
    
    set udg_pf2[1] = 'A11T'
    set udg_pf2[2] = 'A11R'
    set udg_pf2[3] = 'A11S'
    set udg_pf2[4] = 'A13P'
    set udg_pf2[5] = 'A13Q'
    set udg_pf2[6] = 'A13R'
    set udg_pf2[7] = 'A13T'
    set udg_pf2[8] = 'A13Y'
    set udg_pf2[9] = 'A12F'
    set udg_pf2[10] = 'A13X'
    set udg_pf2[11] = 'A13A'
    set udg_pf2[12] = 'A13Z'
    set udg_pf2[13] = 'A140'
    set udg_pf2[14] = 'A141'
    set udg_pf2[15] = 'A142'
    set udg_pf2[16] = 'A143'
    set udg_pf2[17] = 'A144'
    set udg_pf2[18] = 'A145'
    set udg_pf2[19] = 'A146'
    set udg_pf2[20] = 'A147'
    set udg_pf2[21] = 'A12G'
    set udg_pf2[22] = 'A149'
    set udg_pf2[23] = 'A12C'
    set udg_pf2[24] = 'A12H'
    set udg_pf2[25] = 'A14C'
    set udg_pf2[26] = 'A14D'
    set udg_pf2[27] = 'A14E'
    set udg_pf2[28] = 'A12I'
    set udg_pf2[29] = 'A12M'
    set udg_pf2[30] = 'A11U'
    set udg_pf2[31] = 'A11V'
    set udg_pf2[32] = 'A14I'
    set udg_pf2[33] = 'A14J'
    set udg_pf2[34] = 'A14K'
    set udg_pf2[35] = 'A14L'
    set udg_pf2[36] = 'A15G'
    set udg_pf2[37] = 'A15B'
    set udg_pf2[38] = 'A15I'
    set udg_pf2[39] = 'A164'
    set udg_pf2[40] = 'A15J'
    set udg_pf2[41] = 'A14M'
    set udg_pf2[42] = 'A14W'
    set udg_pf2[43] = 'A11x'
    set udg_pf2[44] = 'A15C'
    set udg_pf2[45] = 'A14N'
    set udg_pf2[46] = 'A14P'
    set udg_pf2[47] = 'A14Q'
    set udg_pf2[48] = 'A11W'
    set udg_pf2[49] = 'A120'
    set udg_pf2[50] = 'A14S'
    set udg_pf2[51] = 'A14T'
    set udg_pf2[52] = 'A11Y'
    set udg_pf2[53] = 'A120'
    set udg_pf2[54] = 'A122'
    set udg_pf2[55] = 'A14U'
    set udg_pf2[56] = 'A14V'
    set udg_pf2[57] = 'A15H'
    set udg_pf2[58] = 'A11Z'
    set udg_pf2[59] = 'A14Y'
    set udg_pf2[60] = 'A12R'
    set udg_pf2[61] = 'A12P'
    set udg_pf2[62] = 'A123'
    set udg_pf2[63] = 'A127'
    set udg_pf2[64] = 'A128'
    set udg_pf2[65] = 'A12A'
    set udg_pf2[66] = 'A15L'
    set udg_pf2[67] = 'A15M'
    set udg_pf2[68] = 'A15N'
    set udg_pf2[69] = 'A12B'
    set udg_pf2[70] = 'A129'
    set udg_pf2[71] = 'A12D'
    set udg_pf2[72] = 'A12E'
    set udg_pf2[73] = 'A12U'
    set udg_pf2[74] = 'A15A'
    set udg_pf2[75] = 'A12Q'
    set udg_pf2[76] = 'A14R'
    set udg_pf2[77] = 'A13F'
    set udg_pf2[78] = 'A156'
    
    
endfunction

//===========================================================================
function InitTrig______________PFBL takes nothing returns nothing
    set gg_trg______________PFBL = CreateTrigger()
#ifdef DEBUG
    call YDWESaveTriggerName(gg_trg______________PFBL, "皮肤初始化")
#endif
    call TriggerRegisterTimerEventSingle( gg_trg______________PFBL, 2.00 )
    call TriggerAddAction(gg_trg______________PFBL, function Trig_________________pifchushihuaActions)
endfunction
########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig______________CJBZConditions takes nothing returns boolean
    return test.Enable
endfunction

function Trig______________CJBZFunc006Conditions takes nothing returns nothing
    call RemoveUnit( YDTriggerGetEx(unit, YDTriggerH2I(GetTriggeringTrigger()), 0xD3ACADB7) )
    call EnableTrigger( gg_trg______________CJBZ )
    call YDTriggerClearTable(YDTriggerH2I(GetTriggeringTrigger()))
    call DestroyTrigger(GetTriggeringTrigger())
endfunction

function Trig______________CJBZActions takes nothing returns nothing
    local trigger ydl_trigger
    local integer ydl_localvar_step = YDTriggerGetEx(integer, YDTriggerH2I(GetTriggeringTrigger()), 0xCFDE6C76)
    set ydl_localvar_step = ydl_localvar_step + 3
    call YDTriggerSetEx(integer, YDTriggerH2I(GetTriggeringTrigger()), 0xCFDE6C76, ydl_localvar_step)
    call YDTriggerSetEx(integer, YDTriggerH2I(GetTriggeringTrigger()), 0xECE825E7, ydl_localvar_step)
    call CreateNUnitsAtLoc( 1, 'Hmgd', Player(11), Location(-6900.00, -5000.00), bj_UNIT_FACING )
    call YDTriggerSetEx(unit, YDTriggerH2I(GetTriggeringTrigger())*ydl_localvar_step, 0xD3ACADB7, bj_lastCreatedUnit)
    call UnitAddItemByIdSwapped( 'I057', YDTriggerGetEx(unit, YDTriggerH2I(GetTriggeringTrigger())*ydl_localvar_step, 0xD3ACADB7) )
    call DisableTrigger( GetTriggeringTrigger() )
    set ydl_trigger = CreateTrigger()
    call YDTriggerSetEx(unit, YDTriggerH2I(ydl_trigger), 0xD3ACADB7, YDTriggerGetEx(unit, YDTriggerH2I(GetTriggeringTrigger())*ydl_localvar_step, 0xD3ACADB7))
    call TriggerRegisterPlayerChatEvent( ydl_trigger, Player(0), "/-target", true )
    call TriggerAddCondition(ydl_trigger, Condition(function Trig______________CJBZFunc006Conditions))
    call YDTriggerClearTable(YDTriggerH2I(GetTriggeringTrigger())*ydl_localvar_step)
    set ydl_trigger = null
endfunction

//===========================================================================
function InitTrig______________CJBZ takes nothing returns nothing
    set gg_trg______________CJBZ = CreateTrigger()
#ifdef DEBUG
    call YDWESaveTriggerName(gg_trg______________CJBZ, "创建靶子 CJBZ")
#endif
    call TriggerRegisterPlayerChatEvent( gg_trg______________CJBZ, Player(0), "/-target", true )
    call TriggerAddCondition(gg_trg______________CJBZ, Condition(function Trig______________CJBZConditions))
    call TriggerAddAction(gg_trg______________CJBZ, function Trig______________CJBZActions)
endfunction
########
########

########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig________________uActions takes nothing returns nothing
    set udg_pp[1] = 'A0Z2'
    set udg_pp[2] = 'A0Z1'
    set udg_pp[3] = 'A0Z6'
    set udg_pp[4] = 'A0Z7'
    set udg_pp[5] = 'A0Z8'
    set udg_pp[6] = 'A10D'
    set udg_pp[7] = 'A0ZA'
    set udg_pp[8] = 'A0ZB'
    set udg_pp[9] = 'A0ZC'
    set udg_pp[10] = 'A0ZD'
    set udg_pp[11] = 'A0ZE'
    set udg_pp[12] = 'A0ZF'
    set udg_pp[13] = 'A0ZG'
    set udg_pp[14] = 'A0ZH'
    set udg_pp[15] = 'A0ZI'
    set udg_pp[16] = 'A0ZJ'
    set udg_pp[17] = 'A0ZK'
    set udg_pp[18] = 'A0ZL'
    set udg_pp[19] = 'A0ZM'
    set udg_pp[20] = 'A0ZN'
    set udg_pp[21] = 'A10H'
    set udg_pp[22] = 'A0Z0'
    set udg_pp[23] = 'A0ZQ'
    set udg_pp[24] = 'A0ZR'
    set udg_pp[25] = 'A0ZS'
    set udg_pp[26] = 'A10E'
    set udg_pp[27] = 'A0ZU'
    set udg_pp[28] = 'A0ZV'
    set udg_pp[29] = 'A0ZW'
    set udg_pp[30] = 'A0ZX'
    set udg_pp[31] = 'A0ZY'
    set udg_pp[32] = 'A0ZZ'
    set udg_pp[33] = 'A100'
    set udg_pp[34] = 'A101'
    set udg_pp[35] = 'A102'
    set udg_pp[36] = 'A103'
    set udg_pp[37] = 'A104'
    set udg_pp[38] = 'A105'
    set udg_pp[39] = 'A106'
    set udg_pp[40] = 'A107'
    set udg_pp[41] = 'A108'
    set udg_pp[42] = 'A109'
    set udg_pp[43] = 'A10F'
    set udg_pp[44] = 'A10B'
endfunction

//===========================================================================
function InitTrig________________u takes nothing returns nothing
    set gg_trg________________u = CreateTrigger()
#ifdef DEBUG
    call YDWESaveTriggerName(gg_trg________________u, "表情初始化")
#endif
    call TriggerRegisterTimerEventSingle( gg_trg________________u, 2.00 )
    call TriggerAddAction(gg_trg________________u, function Trig________________uActions)
endfunction
########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########

########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
<?
    update('war3mapskin.txt', '自定义游戏界面',
        function(content)
            local new_lines = {
                {'[FrameDef]', 'CHAT_RECIPIENT_ALLIES', ' '},
                {'[FrameDef]', 'CHAT_RECIPIENT_ALL', '[全体BAKA]'},
                {'[FrameDef]', 'CHAT_RECIPIENT_PRIVATE', '[悄悄话]'},
                {'[FrameDef]', 'CHAT_RECIPIENT_OBSERVERS', '[围观群众]'},
                {'[FrameDef]', 'LOADING_WAITING_FOR_PLAYERS', '等待其他小霸王'}
            }

            local lines = {
                [''] = {}
            }

            for _, line in ipairs(new_lines) do
                local type, name, value = line[1], line[2], line[3]
                if not lines[type] then
                    lines[type] = {}
                    table.insert(lines, type)
                end
                table.insert(lines[type], {name, value})
                lines[name] = true
            end

            local type = ''
            for line in content:gmatch('%C+') do
                if line:sub(1, 1) == '[' and line:sub(-1, -1) == ']' then
                    type = line
                    if not lines[type] then
                        lines[type] = {}
                        table.insert(lines, type)
                    end
                else
                    local n = line:find('=')
                    if n then
                        local name = line:sub(1, n - 1)
                        local value = line:sub(n + 1, -1)
                        if not lines[name] then
                            table.insert(lines[type], {name, value})
                            lines[name] = true
                        end
                    end
                end
            end

            local new_lines = {}

            for _, type in ipairs(lines) do
                table.insert(new_lines, type)
                for _, line in ipairs(lines[type]) do
                    local name, value = line[1], line[2]
                    table.insert(new_lines, ('%s=%s'):format(name, value))
                end
                table.insert(new_lines, '\r\n')
            end

            return table.concat(new_lines, '\r\n')
        end
    )
?>
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
<?
    update('war3map.j', '静态哈希',
        function(content)
            content = content:gsub('StringHash%(%s-%"(.-)%"%s-%)',
                function(s)
                    if not s:match('"') then
                        return string_hash(s)
                    end
                end
            )
            return content
        end
    )

?>
########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0

<?
    --优化逆天
    --local update = function() end
    update('war3map.j', '优化逆天',
        function(content)
            local time = {}
            time[0] = os.clock()

            local function getType(type)
                if type:sub(-6) == 'Handle' then
                    type = type:sub(1, -7):lower()
                elseif type == 'Str' then
                    type = 'string'
                else
                    type = type:lower()
                end
                return type
            end

            local function getType2(type)
                if type == 'string' then
                    type = 'str'
                elseif type == 'fogmodifier' then
                    type = 'fogModifierHandle'
                elseif type == 'texttag' then
                    type = 'textTagHandle'
                elseif type ~= 'integer' and type ~= 'boolean' and type ~= 'real' then
                    type = type .. 'Handle'
                end
                type = type:sub(1, 1):upper() .. type:sub(2)
                return type
            end

            local function getTypeValue(type)
                local value
                if type == 'boolean' then
                    value = 'false'
                elseif type == 'integer' then
                    value = '0'
                elseif type == 'real' then
                    value = '0.'
                elseif type == 'string' then
                    value = '""'
                else
                    value = 'null'
                end
                return value
            end

            local function autoFlush(type)
                return type == 'string' or type == 'boolean' or type == 'integer' or type == 'real'
            end

            local globalList = {}

            local function addGlobal(name, type, value)
                if not globalList[name] then
                    table.insert(globalList, name)
                    globalList[name] = {type, value}
                end
            end

            addGlobal('ydg_index', 'integer', 0)

                --io.save(fs.ydwe_path() / "logs" / "script_lua.j", content)

                    local funcs = {}

                    content = content:gsub('function (Trig_%S+)( takes%C+)(.-)endfunction',
                        function(name, l, s)
                            funcs[name] = {
                                name = name, --名字
                                l = l, --参数
                                s = s, --代码
                                locals = {}, --存放局部变量
                                para_locals = {}, --存放父函数当前的局部变量状态(也就是当前函数可以继承到的变量)
                                need_locals = {}, --存放选取时,子函数的局部变量状态
                                type = {}, --函数的逆天类型(局部/计时器/触发器/选取)
                            }

                            table.insert(funcs, name)
                            return '__THIS_IS_FUNCTION__' .. name .. '__FUNCTION_END__'
                        end
                    )

                    local sys_local_var = {
                        ydl_trigger = true,
                        ydl_trigger_handle = true,
                        ydl_timer = true,
                        ydl_timer_handle = true,
                        ydl_exp_timer_handle = true,
                        ydl_tri_trigger_handle = true,
                    }

                    --对逆天局部变量进行初步优化

                    local function loadFunction(name)
                        local t = funcs[name]
                        if t.loaded then
                            return
                        end

                        t.loaded = true

                        --添加局部变量
                        local function addLocal(name, type, value, i)
                            if not t.locals[name] then
                                if not type then
                                    type = name:match('ydl_(%a+)')
                                end
                                t.locals[name] = {
                                    type,   --类型
                                    value,  --初始值
                                    --fresh,  --更新函数
                                }
                                if i then
                                    table.insert(t.locals, i, name)
                                else
                                    table.insert(t.locals, name)
                                end
                            end
                        end

                        --设置局部变量
                        local function setLocal(name, flag)
                            if flag then
                                t.locals[name].set = t.locals[name].set - 1
                                if t.locals[name].set == 0 then
                                    t.locals[name].set = nil
                                end
                            else
                                t.locals[name].set = (t.locals[name].set or 0) + 1
                            end

                        end

                        --读取局部变量
                        local function getLocal(name, flag)
                            if flag then
                                t.locals[name].get = t.locals[name].get - 1
                                if t.locals[name].get == 0 then
                                    t.locals[name].get = nil
                                end
                            else
                                t.locals[name].get = (t.locals[name].get or 0) + 1
                            end

                        end

                        --保存临时局部变量(直接写在逆天计时器/触发器参数里的)
                        local function saveLocal(name, type, value)
                            t.saves[name] = {type, value}
                        end

                        --return的标记
                        local returnData = {}

                        local function returnMark()
                            local data = {}
                            table.insert(returnData, data)

                            --保存当前的局部变量状态
                            for i, name in ipairs(t.locals) do
                                data[i] = name
                                if not data[name] then
                                    data[name] = {}
                                end
                                for k, v in pairs(t.locals[name]) do
                                    data[name][k] = v
                                end
                            end

                            return '@@return_' .. #returnData
                        end

                        --设置局部变量初始值
                        local function setLocalValue(name, value)
                            local v = t.locals[name]
                            local funcs = {
                                _timer = function()
                                    local vtype = getType2(v[1])
                                    local key = name:match('ydl_%a+_(%w+)')
                                    value = ('Load%s(YDHT, ydl_exp_timer_handle, %s)'):format(vtype, key)
                                    addLocal('ydl_exp_timer_handle', 'integer', 'GetHandleId(GetExpiredTimer())', 1)
                                    setLocal('ydl_exp_timer_handle')
                                end,
                                _trigger = function()
                                    local vtype = getType2(v[1])
                                    local key = name:match('ydl_%a+_(%w+)')
                                    value = ('Load%s(YDHT, ydl_tri_trigger_handle, %s)'):format(vtype, key)
                                    addLocal('ydl_tri_trigger_handle', 'integer', 'GetHandleId(GetTriggeringTrigger())', 1)
                                    setLocal('ydl_tri_trigger_handle')
                                end,
                            }
                            v[2] = funcs[value] and funcs[value]() or value
                            --赋初始值后视为设置(但不需要刷新状态)
                            setLocal(name)

                            --遍历return,进行局部变量状态设置
                            for i, data in ipairs(returnData) do
                                if not data[name] then
                                    data[name] = {}
                                end
                                data[name].set = true
                            end
                        end

                        --设置局部变量更新状态
                        local function setLocalFresh(name, value)
                            local v = t.locals[name]
                            local funcs = {
                                _timer = function()
                                    local vtype = getType2(v[1])
                                    local key = name:match('ydl_%a+_(%w+)')
                                    value = ('call Save%s(YDHT, ydl_exp_timer_handle, %s, %s)'):format(vtype, key, name)
                                    addLocal('ydl_exp_timer_handle', 'integer', 'GetHandleId(GetExpiredTimer())', 1)
                                    setLocal('ydl_exp_timer_handle')
                                end,
                                _trigger = function()
                                local vtype = getType2(v[1])
                                    local key = name:match('ydl_%a+_(%w+)')
                                    value = ('call Save%s(YDHT, ydl_tri_trigger_handle, %s, %s)'):format(vtype, key, name)
                                    addLocal('ydl_tri_trigger_handle', 'integer', 'GetHandleId(GetTriggeringTrigger())', 1)
                                    setLocal('ydl_tri_trigger_handle')
                                end,
                            }
                            v[3] = funcs[value] and funcs[value]() or value
                        end

                        --loop的标记
                        local loop_level = 0
                        local loop_start = 0

                        local function loopMark()
                            loop_level = loop_level + 1
                            if loop_level == 1 then

                                loop_start = #returnData + 1 --用来记录嵌套在loop中的return,以便正确保存数据
                            end
                        end

                        local function endloopMark()
                            loop_level = loop_level - 1
                            if loop_level == 0 then
                                local loop_end = #returnData
                                for i = loop_start, loop_end do
                                    local data = returnData[i]
                                    --保存当前的局部变量状态
                                    for i, name in ipairs(t.locals) do
                                        data[i] = name
                                        data[name] = {}
                                        for k, v in pairs(t.locals[name]) do
                                            data[name][k] = v
                                        end
                                    end
                                end
                            end
                        end

                        --更新局部变量(只更新到目前为止赋值过的局部变量)
                        local function freshLocal(i)
                            local fresh = {}
                            local t = i and returnData[i] or t.locals
                            for _, name in ipairs(t) do
                                local v = t[name]

                                --检查是否需要更新状态
                                if v[3] then
                                    table.insert(fresh, v[3])
                                end
                            end
                            return table.concat(fresh, '\n') .. '\n'
                        end

                        --释放局部变量
                        local function flushLocal(i)
                            local flush = {}
                            local t2 = i and returnData[i] or t.locals
                            for _, name in ipairs(t.locals) do
                                local v = t.locals[name]
                                local type = v[1]
                                --检查是否需要释放
                                if t2[name] and t2[name].set and not autoFlush(type) and not sys_local_var[name] then
                                    table.insert(flush, ('set %s = null'):format(name))
                                end
                            end
                            return table.concat(flush, '\n') .. '\n'
                        end

                        --向子函数保存当前局部变量状态
                        local function saveParaLocal(name)
                            local tt = funcs[name].para_locals

                            for name, v in pairs(t.locals) do
                                if v.set then
                                    tt[name] = v
                                end
                            end

                            for name, v in pairs(t.para_locals) do
                                tt[name] = v
                            end

                            if t.saves then
                                for name, v in pairs(t.saves) do
                                    tt[name] = v
                                end
                            end
                        end

                        --设置为子函数
                        local function setPara(name)
                            funcs[name].para = t.name
                        end

                        t.s = t.s:gsub('[^\n\r]+',
                            function(line)
                                if line:match('local integer ydl_localvar_step') then
                                    --带有逆天局部变量的主函数
                                    t.type['局部'] = true
                                    return ''
                                end

                                line = line:gsub('LoadInteger%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%), 0xECE825E7%)',
                                    function()
                                        t.type['局部'] = true
                                        return 'ydl_localvar_step'
                                    end
                                )

                                if line:match('return') then
                                    return returnMark(line) .. '\n' .. line
                                end

                                if line:match('endloop') then
                                    return endloopMark()
                                end

                                if line:match('loop') then
                                    return loopMark()
                                end

                                --新建逆天计时器
                                if line:match('local timer ydl_timer') then
                                    t.saves = {}
                                    return line .. '\nlocal integer ydl_timer_handle'
                                end

                                line = line:gsub('GetHandleId%(ydl_timer%)',
                                    function()
                                        return 'ydl_timer_handle'
                                    end
                                )

                                line = line:gsub('set ydl_timer = (.+)',
                                    function(value)
                                        if value == 'null' then
                                            return
                                        end
                                        if value == 'GetExpiredTimer()' then
                                            --如果直接拿到期计时器做新的逆天触发器,则保护该地址
                                            line = 'ydl_exp_timer_handle = 0\n' .. line
                                        end
                                        return line .. '\nset ydl_timer_handle = GetHandleId(ydl_timer)'
                                    end
                                )

                                --新建逆天触发器
                                if line:match('local trigger ydl_trigger') then
                                    t.saves = {}
                                    return line .. '\nlocal integer ydl_trigger_handle'
                                end

                                line = line:gsub('GetHandleId%(ydl_trigger%)',
                                    function()
                                        return 'ydl_trigger_handle'
                                    end
                                )

                                if line:match('set ydl_trigger = [^n][^u][^l][^l]') then
                                    line = line .. '\nset ydl_trigger_handle = GetHandleId(ydl_trigger)'
                                end

                                --查找子函数
                                local fname = line:match('function ([%w_]+)')
                                if fname then
                                    local tt = funcs[fname]
                                    if tt then
                                        setPara(fname)
                                        if line:match('call [%w%_%.]-TimerStart%(ydl_timer') then
                                            --逆天计时器子函数
                                            tt.type['计时器'] = true
                                            tt.type['选取'] = false
                                            saveParaLocal(fname)
                                        end
                                        if line:match('call TriggerAddCondition%(ydl_trigger') then
                                            --逆天触发器子函数
                                            tt.type['触发器'] = true
                                            tt.type['选取'] = false
                                            saveParaLocal(fname)
                                        end
                                        if line:match('call ForGroup') or line:match('EnumDestructables') then
                                            --选取单位组子函数
                                            tt.type['选取'] = true
                                            tt.type['计时器'] = t.type['计时器']
                                            tt.type['触发器'] = t.type['触发器']
                                            loadFunction(fname)
                                            local set = {}
                                            local get = {}
                                            for i, name in ipairs(tt.need_locals) do
                                                if tt.need_locals[name].get then
                                                    table.insert(get, ('set %s[ydg_index] = %s'):format(name:gsub('ydl', 'ydg'), name))
                                                    get[name] = true

                                                    --检查是否继承父函数状态
                                                    addLocal(name)
                                                    getLocal(name)
                                                    if t.para_locals[name] then
                                                        if t.type['计时器'] then
                                                            setLocalValue(name, '_timer')
                                                        end
                                                        if t.type['触发器'] then
                                                            setLocalValue(name, '_trigger')
                                                        end
                                                    end

                                                end
                                                if tt.need_locals[name].set then
                                                    table.insert(set, ('set %s = %s[ydg_index]'):format(name, name:gsub('ydl', 'ydg')))
                                                    --即使只赋值,也要赋一个初始值给他
                                                    if not get[name] then
                                                        table.insert(get, ('set %s[ydg_index] = %s'):format(name:gsub('ydl', 'ydg'), name))
                                                    end

                                                    --检查是否继承父函数状态
                                                    addLocal(name)
                                                    setLocal(name)
                                                    if t.para_locals[name] then
                                                        if t.type['计时器'] then
                                                            setLocalFresh(name, '_timer')
                                                        end
                                                        if t.type['触发器'] then
                                                            setLocalFresh(name, '_trigger')
                                                        end
                                                    end

                                                end
                                            end
                                            if not t.type['选取'] and (#set > 0 or #get > 0) then
                                                line = table.concat(
                                                    {
                                                        'set ydg_index = ydg_index + 1',
                                                        table.concat(get, '\n'),
                                                        line,
                                                        table.concat(set, '\n'),
                                                        'set ydg_index = ydg_index - 1'
                                                    },
                                                '\n')
                                            end
                                        end
                                    end
                                end

                                if line:match('set ydl_localvar_step') then
                                    return ''
                                end
                                if line:sub(-18, -1) == 'ydl_localvar_step)' then
                                    return ''
                                end

                                if t.type['局部'] then
                                    line = line:gsub('Load(%a+)%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%)%*ydl_localvar_step, (%w+)%)',
                                        function(vtype, key)
                                            local type = getType(vtype)
                                            local name = ('ydl_%s_%s'):format(type, key)
                                            addLocal(name)
                                            getLocal(name)

                                            if t.type['选取'] then
                                                name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                            end

                                            return name
                                        end
                                    )

                                    local vtype, key, value = line:match('call Save(%a+)%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%)%*ydl_localvar_step, (%w+), (.+)%)')
                                    if vtype then
                                        local type = getType(vtype)
                                        local name = ('ydl_%s_%s'):format(type, key)
                                        addLocal(name)
                                        setLocal(name)

                                        if t.type['选取'] then
                                            name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                        end

                                        line = ('set %s = %s'):format(name, value)
                                    end
                                end

                                if t.type['计时器'] then
                                    line = line:gsub('Load(%a+)%(YDHT, GetHandleId%(GetExpiredTimer%(%)%)%, (%w+)%)',
                                        function(vtype, key)
                                            local type = getType(vtype)
                                            local name = ('ydl_%s_%s'):format(type, key)
                                            addLocal(name)
                                            getLocal(name)

                                            --检查是否继承父函数状态
                                            if t.para_locals[name] then
                                                setLocalValue(name, '_timer')
                                            end

                                            if t.type['选取'] then
                                                name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                            end

                                            return name
                                        end
                                    )

                                    local vtype, key, value = line:match('call Save(%a+)%(YDHT, GetHandleId%(GetExpiredTimer%(%)%)%, (%w+), (.+)%)')
                                    if vtype then
                                        local type = getType(vtype)
                                        local name = ('ydl_%s_%s'):format(type, key)
                                        addLocal(name)
                                        setLocal(name)

                                        --检查是否继承父函数状态
                                        if t.para_locals[name] then
                                            setLocalFresh(name, '_timer')
                                        end

                                        if t.type['选取'] then
                                            name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                        end

                                        if value == 'null' then
                                            line = ('call RemoveSavedHandle(YDHT, ydl_exp_timer_handle, %s)\nset %s = %s'):format(key, name, value)
                                        else
                                            line = ('set %s = %s'):format(name, value)
                                        end
                                    end

                                    --检查是否在选取中对到期的计时器地址有需求
                                    if t.type['选取'] and line:match('ydl_exp_timer_handle') then
                                        addLocal('ydl_exp_timer_handle', 'integer', 'GetHandleId(GetExpiredTimer())')
                                        setLocal('ydl_exp_timer_handle')
                                    end

                                    if line:match('call FlushChildHashtable%(YDHT, GetHandleId%(GetExpiredTimer%(%)%)%)') then
                                        addLocal('ydl_exp_timer_handle', 'integer', 'GetHandleId(GetExpiredTimer())')
                                        setLocal('ydl_exp_timer_handle')
                                        return 'call FlushChildHashtable(YDHT, ydl_exp_timer_handle)\nset ydl_exp_timer_handle = 0'
                                    end

                                end

                                if t.type['触发器'] then

                                    line = line:gsub('Load(%a+)%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%)%, (%w+)%)',
                                        function(vtype, key)
                                            local type = getType(vtype)
                                            local name = ('ydl_%s_%s'):format(type, key)
                                            addLocal(name)
                                            getLocal(name)

                                            --检查是否继承父函数状态
                                            if t.para_locals[name] then
                                                setLocalValue(name, '_trigger')
                                            end
                                            if t.type['选取'] then
                                                name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                            end

                                            return name
                                        end
                                    )

                                    local vtype, key, value = line:match('call Save(%a+)%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%)%, (%w+), (.+)%)')
                                    if vtype then
                                        local type = getType(vtype)
                                        local name = ('ydl_%s_%s'):format(type, key)
                                        addLocal(name)
                                        setLocal(name)

                                        --检查是否继承父函数状态
                                        if t.para_locals[name] then
                                            setLocalFresh(name, '_trigger')
                                        end
                                        if t.type['选取'] then
                                            name = ('ydg_%s_%s[ydg_index]'):format(type, key)
                                        end

                                        if value == 'null' then
                                            line = ('call RemoveSavedHandle(YDHT, ydl_tri_trigger_handle, %s)\nset %s = %s'):format(key, name, value)
                                        else
                                            line = ('set %s = %s'):format(name, value)
                                        end

                                    end

                                    --检查是否在选取中对触发的触发器地址有需求
                                    if t.type['选取'] and line:match('ydl_tri_trigger_handle') then
                                        addLocal('ydl_tri_trigger_handle', 'integer', 'GetHandleId(GetTriggeringTrigger())')
                                        setLocal('ydl_tri_trigger_handle')
                                    end

                                    if line:match('call FlushChildHashtable%(YDHT, GetHandleId%(GetTriggeringTrigger%(%)%)%)') then
                                        addLocal('ydl_tri_trigger_handle', 'integer', 'GetHandleId(GetTriggeringTrigger())')
                                        setLocal('ydl_tri_trigger_handle')
                                        return 'call FlushChildHashtable(YDHT, ydl_tri_trigger_handle)\nset ydl_tri_trigger_handle = 0'
                                    end

                                end

                                --检查新建逆天计时器的冗余代码
                                local vtype, key, value = line:match('call Save(%a+)%(YDHT, ydl_timer_handle, (%w+), (.+)%)')
                                if vtype then
                                    local type = getType(vtype)
                                    local name = ('ydl_%s_%s'):format(type, key)
                                    if name == value then
                                        --正在保存变量本身
                                        if not t.locals[name].set then
                                            getLocal(name, true)
                                            return ''
                                        end
                                    else
                                        saveLocal(name, type, value)
                                    end
                                end

                                --检查新建逆天触发器的冗余代码
                                local vtype, key, value = line:match('call Save(%a+)%(YDHT, ydl_trigger_handle, (%w+), (.+)%)')
                                if vtype then
                                    local type = getType(vtype)
                                    local name = ('ydl_%s_%s'):format(type, key)
                                    if name == value then
                                        --正在保存变量本身
                                        if not t.locals[name].set then
                                            getLocal(name, true)
                                            return ''
                                        end
                                    else
                                        saveLocal(name, type, value)
                                    end
                                end


                                return line
                            end
                        )

                        --修改return
                        t.s = t.s:gsub('@@return_(%d+)',
                            function(i)
                                i = tonumber(i)
                                if not t.type['选取'] then
                                    return freshLocal(i) .. flushLocal(i)
                                else
                                    return ''
                                end
                            end
                        )
                        
                        --手动更新标记
                        t.s = t.s:gsub('@@fresh_locals', freshLocal())
                        
                        if not t.type['选取'] then
                            --在函数尾部更新局部变量
                            t.s = t.s .. freshLocal()

                            --在函数尾部释放局部变量
                            t.s = t.s .. flushLocal()
                        end

                        --生成局部变量
                        local loc_define = {}
                        for _, name in ipairs(t.locals) do
                            local v = t.locals[name]
                            if v.set or v.get then
                                local type = v[1]
                                if t.type['选取'] and not sys_local_var[name] then
                                    addGlobal(name:gsub('ydl', 'ydg'), type, 'array')
                                    if not t.need_locals[name] then
                                        table.insert(t.need_locals, name)
                                        local tt = {}
                                        t.need_locals[name] = tt
                                        for k, v in pairs(v) do
                                            tt[k] = v
                                        end
                                    end
                                else
                                    local value = v[2] or getTypeValue(type)
                                    local line = ('local %s %s = %s'):format(type, name, value)
                                    table.insert(loc_define, line)
                                end
                            end
                        end

                        --在函数顶部声明局部变量
                        t.s = table.concat(loc_define, '\n') .. t.s
                    end

                    --遍历
                    for i = #funcs, 1, -1 do
                        local name = funcs[i]
                        loadFunction(name)
                    end

                    content = content:gsub('__THIS_IS_FUNCTION__([%w_]+)__FUNCTION_END__',
                        function(name)
                            if name and funcs[name] then
                                return 'function ' .. name .. funcs[name].l .. '\n' .. funcs[name].s .. '\nendfunction'
                            end
                        end
                    )

                    --静态全局变量

                    local event_key = string_hash '事件'
                    local event_key2    = string_hash '事件返回'

                    content = content:gsub('Load(%a+)%(YDHT, (0x%w+), (0x%w+)%)',
                        function(vtype, k1, k2)
                            local type = getType(vtype)
                            local name = ('ydg_%s_%s_%s'):format(type, k1, k2)

                            --对事件变量进行特例
                            if k1 == event_key then
                                addGlobal(name, type, 'array')
                                return name .. '[Event.index]'
                            elseif k1 == event_key2 then
                                name = ('ydg_%s_%s_%s'):format(type, event_key, k2)
                                addGlobal(name, type, 'array')
                                return name .. '[Event.index + 1]'
                            else
                                addGlobal(name, type, getTypeValue(type))
                                return name
                            end
                        end
                    )

                    content = content:gsub('call Save(%a+)%(YDHT, (0x%w+), (0x%w+), (%C+)%)',
                        function(vtype, k1, k2, v)
                            local type = getType(vtype)
                            local name = ('ydg_%s_%s_%s'):format(type, k1, k2)

                            --对事件变量进行特例
                            if k1 == event_key then
                                addGlobal(name, type, 'array')
                                return ('set %s[Event.index + 1] = %s'):format(name, v)
                            elseif k1 == event_key2 then
                                name = ('ydg_%s_%s_%s'):format(type, event_key, k2)
                                addGlobal(name, type, 'array')
                                return ('set %s[Event.index] = %s'):format(name, v)
                            else
                                addGlobal(name, type, getTypeValue(type))
                                return ('set %s = %s'):format(name, v)
                            end
                        end
                    )

                    content = content:gsub('Save(%a+)%(YDHT, (0x%w+), (0x%w+), (%C+)%)',
                        function(vtype, k1, k2, v)
                            local type = getType(vtype)
                            local name = ('ydg_%s_%s_%s'):format(type, k1, k2)

                            --对事件变量进行特例
                            if k1 == event_key then
                                addGlobal(name, type, 'array')
                                return ('set %s[Event.index + 1] = %s'):format(name, v)
                            elseif k1 == event_key2 then
                                name = ('ydg_%s_%s_%s'):format(type, event_key, k2)
                                addGlobal(name, type, 'array')
                                return ('set %s[Event.index] = %s'):format(name, v)
                            else
                                addGlobal(name, type, getTypeValue(type))
                                return ('set %s = %s'):format(name, v)
                            end
                        end
                    )

                    io.save(fs.ydwe_path() / "logs" / "script_lua.j", content)

                time[1] = os.clock()


                addGlobal('MU_UPDATE_RESULT_1', 'string', ('"优化总用时:%.3f秒"'):format(time[1] - time[0]))

                --生成全局变量
                local function getGlobal()
                    local list = {}
                    for i, name in ipairs(globalList) do
                        local t = globalList[name]
                        local type, value = t[1], t[2]
                        if value == 'array' then
                            table.insert(list, ('%s array %s'):format(type, name))
                        else
                            table.insert(list, ('%s %s = %s'):format(type, name, value))
                        end
                    end
                    return table.concat(list, '\n')
                end

                content = content .. '\nglobals\n' .. getGlobal() .. '\nendglobals\n'


            return content
        end
    )

?>
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
<?
    --静态命令字符
    update('war3map.j', '静态命令',
        function(content)
            content = content:gsub('String2OrderIdBJ%(%s-%"(%a+)%"%s-%)',
                function(s)
                    return order2id[s]
                end
            )
            
            content = content:gsub('OrderId%(%s-%"(%a+)%"%s-%)',
                function(s)
                    return order2id[s]
                end
            )
            return content
        end
    )
?>
########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
<?

    update('war3map.j', '优化脚本',
        function(content)
            content = content:gsub('== true', '')
            content = content:gsub('else[%c%s]+endif', 'endif')
            return content
        end
    )

?>
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
<?

    update('war3map.j', '哈希表保存null',
        function(content)
            content = content:gsub('Save%a-Handle%((%C-), null%)',
                function(s)
                    return ('RemoveSavedHandle(%s)'):format(s)
                end
            )
            return content
        end
    )

?>
########
########
//TESH.scrollpos=-1
//TESH.alwaysfold=0
<?

    --修改版本号,在地图情节中设置版本号后自动修改其他几处
    ----游戏界面
    ----脚本中所有的__MAP_VER_NAME__标记
    update('war3map.j', '游戏版本号',
        function(content)
            local char_name = content:match([[SetMapName%( "TRIGSTR_(.-)" %)]])

            --版本号文本的字符串id
            local ver_name_id = tonumber(char_name)

            local name_id

            --寻找游戏界面中的文本
            update('war3mapskin.txt', '游戏版本号-skin',
                function(txt)
                    name_id = tonumber(txt:match([[UPKEEP_NONE=TRIGSTR_(%d+)]]))
                end
            )

            local ver_name --保存版本号,例如"2.6H"

            --处理游戏界面
            update('war3map.wts', '游戏版本号-wts',
                function(txt)
                    if ver_name_id then
                        ver_name = txt:match(([[STRING %d.-{.-(%%d%%.%%d.).-}]]):format(ver_name_id))
                    else
                        ver_name = content:match([[SetMapName%( ".-(%d%.%d.).-" %)]])
                    end

                    txt = txt:gsub(([[(STRING %d%%D-{%%c+)(.-)(%%c+})]]):format(name_id), ([[%%1%s%%3]]):format("|cff00ff00全明星战役|cffffff00" .. ver_name))

                    txt = txt:gsub('__MAP_VER_NAME__', ver_name)

                    return txt
                end
            )

            --修改地图中所有的__MAP_VER_NAME__标记
            content = content:gsub('__MAP_VER_NAME__', ver_name)
            return content

        end
    )

?>
########
########
//TESH.scrollpos=0
//TESH.alwaysfold=0
<?

    --将所有的换行符修改为 \r\n 格式
    update('war3map.j', '换行符', function(content)
        local content = content:gsub('%c+', '\r\n')
        return content
    end)
    
?>
########
