Во время разработки обновы для Renewation возникла необходимость ограничить спаун ящиков определенной зоной / зонами на карте. Подобное в игре сделано на картах режима Дом родной (Homelands), но работает на уровне движка. Поэтому встала задача написать свой скрипт, который дублирует вшитые в игру функции по спауну случайных ящиков (с учетом настроек вероятностей ящиков в игровой схеме). Минусы - мы не можем через скрипты дропать ящики на случайные координаты в пространстве. Спаун либо совсем рандомный (что не подходит), либо в точках заранее размещенных эмиттеров. Пришлось использовать последний вариант - 16 точек спауна для ящиков, заранее раставленные, но выбираем из них место каждый раз случайно. Первая проблема, что это не очень большая вариативность и периодически будет дропаться несколько ящиков в одной точке. Вторая проблема, что мы не можем проверить наличие земли под ящиком в случае разрушения уровня, тогда ящики будут сразу падать в воду, либо надо отключать им гравитацию и они будут висеть в небе. Еще при подборе "дождя из ящиков" (crate shower) запускается игровая логика, выбрасывающая ящики в обход этого скрипта, т.е. в любом месте. Кроме того, данная реализация скрипта использует встроенный в игру генератор случайных чисел, у которой наблюдается одна проблема - семя (seed) для получения числа в диапазоне меняется один раз за ход, а значит если мы спауним через скрипт несколько ящиков в один ход - это будут одинаковые ящики дропнутые в одной точке. Кидаю скрипт сюда, возможно кому-нибудь будет полезен, например при разработке своих скриптов. Например, здесь можно посмотреть, как дропнуть абсолютно любой ящик в игре.
Если скрипт будет улучшаться - буду обновлять и в этой теме.
Код
function SetupSchemeCrates() -- запускаем один раз, для записи настроек схемы SchemeWeaponsMax = 0 SchemeMysteryMax = 0 SchemeUtilityMax = 0
-- прогоняем все типы ящиков и складываем их шансы выпадения. Это понадобится для понимания диапазона генератор чисел for i = 1,29 do SchemeWeaponsMax = SchemeWeaponsMax + RandomCrates[i].chance end for i = 30,44 do SchemeMysteryMax = SchemeMysteryMax + RandomCrates.chance end for i = 45,58 do SchemeUtilityMax = SchemeUtilityMax + RandomCrates.chance end end function SpawnSchemeCrate() local crateRand = lib_GetRandom(1,10)
if SchemeCrateChance >= crateRand then -- дропаем ли ящик (вероятность)? SetData("Crate.Index", -1) SetData("Crate.GroundSnap", 1) local crateRand = lib_GetRandom(1,16) SetData("Crate.Spawn", "RandomCrate" .. crateRand) SetData("Crate.RandomSpawnPos", 0) SetData("Crate.Type", RandomCrates[2].type) SetData("Crate.Contents", RandomCrates[2].name ) SetData("Crate.NumContents", 1) SetData("Crate.GroundSnap", 1) SetData("Crate.Gravity", 1) SetData("Crate.TeamCollectable", -1)
crateRand = lib_GetRandom(1,SchemeWeaponChance+SchemeMysteryChance+SchemeUtilityChance+SchemeHealthChance) -- сложили вероятности всех типов ящиков, чтобы задать диапазон для генератора чисел, а далее от выпавшего числа считаем, какой конкретно тип дропать local setCol = 0 if crateRand <= SchemeWeaponChance then SetData("Crate.Type", "Weapon") SetData("Crate.NumContents", 1) crateRand = lib_GetRandom(1,SchemeWeaponsMax) -- аналогично получаем случайное число на все оружия и дропаем соответствующий ящик с оружием setCol = 0 for i = 1,29 do setCol = setCol + RandomCrates.chance if crateRand < setCol then SetData("Crate.Contents", RandomCrates.name ) break end end elseif crateRand <= SchemeWeaponChance+SchemeMysteryChance then SetData("Crate.Type", "Mystery") SetData("Crate.NumContents", 1) crateRand = lib_GetRandom(1,SchemeMysteryMax) -- то же самое повторяем для ящиков Мистерии и Утилит setCol = 0 for i = 30,44 do setCol = setCol + RandomCrates.chance if crateRand < setCol then SetData("Crate.Contents", RandomCrates.name ) break end end elseif crateRand <= SchemeWeaponChance+SchemeMysteryChance+SchemeUtilityChance then SetData("Crate.Type", "Utility") SetData("Crate.NumContents", 1) crateRand = lib_GetRandom(1,SchemeUtilityMax) setCol = 0 for i = 45,58 do setCol = setCol + RandomCrates.chance if crateRand < setCol then SetData("Crate.Contents", RandomCrates.name ) break end end else SetData("Crate.Type", "health") SetData("Crate.NumContents", SchemeHealthInCrates) SetData("Crate.Contents", "health") end SendMessage("GameLogic.CreateCrate") end
end [/i]
Для запуска скрипта мы в начале запускаем функцию SetupSchemeCrates() для получения настроек схемы (один раз в самом начале), а далее когда необходимо заспаунить ящик делаем SpawnSchemeCrate()
Смысл жизни в том, чтобы жизнь имела смысл... (firsacho 2005) Рай придуман, чтобы не страшно было умирать. Ад придуман, чтобы не страшно было жить. (firsacho 2007) Мир делиться на два типа людей: Бездарные трудоголики и Талантливые лентяи. (firsacho 2008)