XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Барахолка
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Msey
????
offline
Опыт: 67,346
Активность:
[SiMiS]Simple Missile System
((центр
Simple Missile System (система 3D снарядов)
))
Автор: Msey
Cинтаксис: vJass (для удобства сделал без cJass)
Думаю, особое разъяснение не нужно, что это за система..
Снаряд:
  • взаимодействует с ландшафтом
  • таким же образом взаимодействует и с водой
  • отскакивает от склонов и возвышенностей
  • легко настраивается
  • работает даже на слабом компе
  • почти легко импортируется
  • чистый кастом скрипт
  • работает без хеш-таблицы
  • работает через структуры
Чейнджлог:
1.0: Релиз системы.
2.0: Полностью переписан движок системы под структуры, теперь система требует 2 библиотеки: TimerUtils и Вoundaries, избавился от хеш-таблицы, убрал лишние функции
((кат v2.0
((код vjass
library A initializer Missile requires TimerUtils optional Boundaries
globals
private group g = CreateGroup() группа для нанесения урона
private constant integer MISSILE = 'h006' id дамми снаряда
private constant string land = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl" эффект при падении на землю
private constant string water = "Abilities\\Weapons\\GryphonRiderMissile\\GryphonRiderMissileTarget.mdl" эффект при падении на воду
private constant string explode = "Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl" эффект взрыва снаряда
private constant real spd = 0.02 период срабатывания тймера
private constant real ConstH = 40 +- 20 скорость
private constant real DMG = 0 +1-100000 урон в области при взрыве
private constant real FACTOR = 50 +- 15 коэфф. при начальном выстреле
private constant real FACToR = 0 +1-2 ограничивающий коэфф прыжка
private constant real HMAX = 40 +-10 высота прыжка
private constant real REDUCE = 1 +-0.5 коэфф. уменьшения скорости
private constant real JUMP = 20 +- 3-7 крен прыжка + доп изменения
endglobals
struct Data
unit Ball
effect e
real Height
real HeightDiff
real MoveSpeed
real MoveAngle
real x
real y
location MovePoint
location cpdx
location cpdy
integer cpdxz
integer cpdyz
real z
destructable dest
rect r
real tempSpeed
real tempHeightDiff
real Angle
real i
real is
real j
real js

public method VectorSize takes location MovePoint returns rect
set .x = GetLocationX(.MovePoint)
set .y = GetLocationY(.MovePoint)
return Rect(.x-50,.y-50,.x+50,.y+50)
endmethod
public method DBP takes unit Ball, location MovePoint returns real
set .i = GetLocationX(.MovePoint)
set .is = GetUnitX(.Ball)
set .j = GetLocationY(.MovePoint)
set .js = GetUnitX(.Ball)
return SquareRoot((.i-.is)*(.i-.is)+(.j-.js)*(.j-.js))
endmethod

public method BounceEffect takes location MovePoint returns nothing
set .x = GetLocationX(.MovePoint)
set .y = GetLocationY(.MovePoint)
if (IsTerrainPathable(.x, .y, PATHING_TYPE_FLOATABILITY) == true) then
set .e = AddSpecialEffect(land, .x,.y )
else
set .e = AddSpecialEffect(water,.x,.y )
endif
call DestroyEffect(.e)
set .e = null
endmethod
private static method MoveLoc takes location HLoc, real Dist, real Angle returns location
call MoveLocation(HLoc,GetLocationX(HLoc)+Dist*Cos(Angle*0.0175),GetLocationY(HLoc)+Dist*Sin(Angle*0.0175​))
return HLoc
endmethod
private static method FilterUnits takes nothing returns boolean
if (IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO)) then
return true
endif
return false
endmethod

private static method FilterDestr takes nothing returns boolean
if (GetDestructableLife(GetFilterDestructable()) >= 0.405 ) then
return true
endif
return false
endmethod

static method checkId takes nothing returns boolean
return GetSpellAbilityId() == 'A00F'
endmethod

static method BallMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local Data this = GetTimerData(t)
set .Angle = .MoveAngle
set .cpdx = Location(GetLocationX(.MovePoint)+2*.MoveSpeed*Cos(.MoveAngle*0.017496),GetLocationY(.MovePoint)+1*.​MoveSpeed*Sin(.MoveAngle*0.017496))
set .cpdy = Location(GetLocationX(.MovePoint)+1*.MoveSpeed*Cos(.MoveAngle*0.017496),GetLocationY(.MovePoint)+2*.​MoveSpeed*Sin(.MoveAngle*0.017496))
set .cpdxz = GetTerrainCliffLevel(GetLocationX(.cpdx), GetLocationY(.cpdx)) - GetTerrainCliffLevel(GetLocationX(.MovePoint), GetLocationY(.MovePoint))
set .cpdyz = GetTerrainCliffLevel(GetLocationX(.cpdy), GetLocationY(.cpdy)) - GetTerrainCliffLevel(GetLocationX(.MovePoint), GetLocationY(.MovePoint))
set .z = GetLocationZ(.MovePoint)
if (I2R(.cpdxz)*100>.Height) then
set .MoveAngle = 180 - .MoveAngle
set .MoveSpeed = .MoveSpeed - 1
endif
if (I2R(.cpdyz)*100>.Height) then
set .MoveAngle = 0 - .MoveAngle
set .MoveSpeed = .MoveSpeed - 1
endif

call MoveLoc(.MovePoint,.MoveSpeed,.MoveAngle)
set .z = .z - GetLocationZ(.MovePoint)
set .Height = .Height + .HeightDiff + .z
set .HeightDiff = .HeightDiff-0.75

if .Height<500 then
set .r = (VectorSize(.MovePoint))
call GroupEnumUnitsInRangeOfLoc(g, .MovePoint, 200, Condition(function Data.FilterUnits))
set .dest = RandomDestructableInRectBJ(.r, Condition(function Data.FilterDestr))
if (.dest != null) then
call RemoveUnit(.Ball)
call ReleaseTimer(t)
call RemoveRect(.r)
endif
if .Height<2.5 then
if CountUnitsInGroup(g)>0 then
call DestroyEffect(AddSpecialEffectLoc(explode, Location(GetLocationX(GetUnitLoc(.Ball)), GetLocationY(GetUnitLoc(.Ball)))) )
call UnitDamagePoint(.Ball, 0., 150 , GetUnitX(.Ball), GetUnitY(.Ball), DMG, true, true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_ACID, WEAPON_TYPE_AXE_MEDIUM_CHOP )
call RemoveUnit(.Ball)
call ReleaseTimer(t)
set t=null
else
if .MoveSpeed>3 then
set .HeightDiff = -0.8*.HeightDiff
set .Height = HMAX
set .MoveSpeed = .MoveSpeed - REDUCE
call BounceEffect(.MovePoint)
else
call DestroyEffect(AddSpecialEffectLoc(explode, Location(GetLocationX(GetUnitLoc(.Ball)), GetLocationY(GetUnitLoc(.Ball)))))
call RemoveUnit(.Ball)
set .Ball = null
call ReleaseTimer(t)
set t=null
endif
endif
endif
endif
call SetUnitPositionLoc(.Ball, .MovePoint)
call SetUnitFacing(.Ball, .MoveAngle)
call SetUnitFlyHeight(.Ball,.Height,0)
call RemoveLocation(.cpdx)
call RemoveLocation(.cpdy)
set .cpdx = null
set .cpdy = null
set .dest = null
set .r = null
set t=null
endmethod

static method Shell takes player co,location cp, location tp, real dist returns thistype

local Data this = .allocate()
local timer t = NewTimer()
set .Height = ConstH
set .HeightDiff = JUMP
set .MoveSpeed = dist/FACTOR
set .MoveAngle = bj_RADTODEG * Atan2(GetLocationY(tp) - GetLocationY(cp), GetLocationX(tp) - GetLocationX(cp))
set .MovePoint = Location(GetLocationX(cp),GetLocationY(cp))
set .Ball =CreateUnitAtLoc(co,MISSILE,cp,.MoveAngle)
call SetUnitPathing(.Ball,false)
call UnitAddAbility(.Ball,'Amrf')
call UnitRemoveAbility(.Ball,'Amrf')
call SetTimerData(t,this)
call TimerStart(t, spd, true, function Data.BallMove)
set t=null
return this
endmethod
endstruct
private struct once
unit c
player co
location cp
location tp
integer i
real y1
real y2
real x1
real x2
real dist
static method LoadStart takes nothing returns nothing
local once this = .allocate()
set .c = GetTriggerUnit()
set .co = GetOwningPlayer(.c)
set .cp = GetUnitLoc(.c)
set .tp = GetSpellTargetLoc()
set .i = GetPlayerId(.co)
set .y1 = GetLocationY(.cp)
set .y2 = GetLocationY(.tp)
set .x1 = GetLocationX(.cp)
set .x2 = GetLocationX(.tp)
set .dist = SquareRoot((.x2-.x1)*(.x2-.x1)+(.y2-.y1)*(.y2-.y1))
call Data.Shell(.co,.cp,.tp,.dist)
call RemoveLocation(.cp)
call RemoveLocation(.tp)
call this.destroy()
endmethod
endstruct
private function Missile takes nothing returns nothing
local trigger t = CreateTrigger()
local playerunitevent pui = EVENT_PLAYER_UNIT_SPELL_EFFECT
call TriggerRegisterPlayerUnitEvent(t, Player(0), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(1), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(2), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(3), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(4), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(5), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(6), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(7), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(8), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(9), pui, null)
call TriggerRegisterPlayerUnitEvent(t, Player(10), pui, null)
call TriggerAddCondition( t, Condition( function Data.checkId ) )
call TriggerAddAction( t, function once.LoadStart )
set t = null
set pui = null
endfunction
endlibrary
library TimerUtils initializer init
globals
private constant boolean USE_HASH_TABLE = false
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET
private constant integer QUANTITY = 256
private constant integer ARRAY_SIZE = 8190
endglobals
==================================================================================================​?
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if(USE_HASH_TABLE) then
new blue
call SaveInteger(ht,0,GetHandleId(t), value)

elseif (USE_FLEXIBLE_OFFSET) then
orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
new blue
return LoadInteger(ht,0,GetHandleId(t) )

elseif (USE_FLEXIBLE_OFFSET) then
orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
use a totally random number here, the more improbable someone uses it, the better.
endglobals
==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
If this happens then the QUANTITY rule has already been broken, try to fix the
issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
set tT[0]=CreateTimer()
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==ARRAY_SIZE) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
local integer i=0
local integer o=-1
local boolean oops = false

static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop

if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
If this message doesn't appear then there is so much
handle id fragmentation that it was impossible to preload
so many timers and the thread crashed! Therefore this
debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary
library Boundaries initializer init
globals
private constant real EXTRA = 500.0
endglobals
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
set t=null
set r=null
set rc=null
endfunction
endlibrary
))
))
Прикрепленные файлы
Тип файла: w3x Example.w3x (40.8 Кбайт, 17 просмотров )
Тип файла: w3x Example_v2.0.w3x (43.8 Кбайт, 80 просмотров )

Отредактировано Msey, 15.06.2012 в 23:08.
Старый 27.04.2012, 20:15
Cosonic5
Моймозггоритогнем
offline
Опыт: 13,584
Активность:
Молодец! А jngp надо?

Отредактировано Msey, 21.05.2012 в 18:37.
Старый 27.04.2012, 20:26
Msey
????
offline
Опыт: 67,346
Активность:
Cosonic5, да.
Зато адик не нужен)

уважительная просьба указывать на ошибки в коде.
Старый 27.04.2012, 20:31
Msey
????
offline
Опыт: 67,346
Активность:

Вышла версия 2.0

Старый 19.05.2012, 15:05
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,259
Активность:
Msey, чё теперь онли структуры и таймер утилс?
Ну производительность то стала ощутимо выше, или всё тока реклама?
Старый 19.05.2012, 15:15
Vadik29
Choice Battle 1.6а
offline
Опыт: 15,845
Активность:
Msey, понравилось + и работает быстро....
Старый 19.05.2012, 15:17
Msey
????
offline
Опыт: 67,346
Активность:
чё теперь онли структуры и таймер утилс?
да. теперь производительность стала значительно выше.
У меня не лагало даже при 60+ снарядах
Старый 19.05.2012, 15:17
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,259
Активность:
Msey, Ну что сказать, круто - плюсую!
Конешно хотелось бы более оригинального падания в воду, но аналог такой системы я видел только в пудж варс, возможно буду юзать более урезаную версию для одной краты, появилась идея нестандартного скилла...
Старый 19.05.2012, 15:24
Doc

offline
Опыт: 63,163
Активность:
У меня не лагало на структурах при 400 снарядах. =)
Старый 19.05.2012, 15:28
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,259
Активность:
Doc, ну от компа зависит, это раз, два такое кол во снарядов не имеет практического смысла, ну что это за мапа такая где вся карта это одни снаряды?
Старый 19.05.2012, 15:30
Msey
????
offline
Опыт: 67,346
Активность:
Я с большим количеством просто не проверял. Потом попробую разогнать до 150 и более)
Старый 19.05.2012, 15:30
Hate
конь вакуумный
offline
Опыт: 43,030
Активность:
хорошая системка)
кстати есть один баг, скрин от
гранаты забились в угол и оооочень долго там прыгают.
Миниатюры
Кликните на картинку для увеличения
Название:  22222.JPG
Просмотров: 73
Размер:  141.9 Кбайт  
Старый 19.05.2012, 15:30
Msey
????
offline
Опыт: 67,346
Активность:
Hatsume_Hate, это не баг. система Boundaries не дает им улететь за границы карты. А прыгают они долго, потому что я поставил коэффициент уменьшения прыжка на минималку, чтобы показать гибкость системы и что она не лагает при большом кол-ве снарядов.
Старый 19.05.2012, 15:33
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,259
Активность:
Msey, кстати а с блокираторами путей она взаимодействует?
Было бы удобно ограждать ими участки карты в которые не должен улетать снаряд...
Старый 19.05.2012, 15:35
Hate
конь вакуумный
offline
Опыт: 43,030
Активность:
Msey:
Hatsume_Hate, это не баг. система Boundaries не дает им улететь за границы карты. А прыгают они долго, потому что я поставил коэффициент уменьшения прыжка на минималку, чтобы показать гибкость системы и что она не лагает при большом кол-ве снарядов.
так они там и остаются навечно. И не улетают оттуда.
Старый 19.05.2012, 15:37
Msey
????
offline
Опыт: 67,346
Активность:
quq_CCCP:
кстати а с блокираторами путей она взаимодействует?
взаимодействует. он уничтожается при прикосновении
    if (.dest != null) then
      call RemoveUnit(.Ball)
      call ReleaseTimer(t)
      call RemoveRect(.r)
мб вскоре я сделаю так, чтобы от отскакивал обратно
Hatsume_Hate,
так они там и остаются навечно. И не улетают оттуда.
тк они движутся в направлении к границам, а границы возвращают отрицательные единицы их смещения, вот поэтому они и прыгают на месте.

Проверил со 150 снарядами, игра начала глючить. Видимо сам процесс подлагивает
Старый 19.05.2012, 15:45
quq_CCCP
Я белый и пушистый!
offline
Опыт: 93,259
Активность:
Msey:

Проверил со 150 снарядами, игра начала глючить. Видимо сам процесс подлагивает
Видим дело в моделях снарядов, попробуй использовать снаряды попроще...
И юнитов с пустыми моделями, если лагов будет меньшее время, значит алгоритм не тормозит, а если нечего не изменится, можно будет пересмотреть сам процесс... Но по мне 150 снарядов более чем достаточно...
Насчёт блокираторов - мб сделать параметр не ломать а отскакивать от блокиратора?
Старый 19.05.2012, 15:49
Doc

offline
Опыт: 63,163
Активность:
quq_CCCP, 1.4 ггц одноядерный проц у меня был тогда. Модель - снаряд атаки тралла. И омг, такая задумка карты была.
Doc добавил:
Глянул код.
You're doing it wrong.
Старый 19.05.2012, 15:55
Msey
????
offline
Опыт: 67,346
Активность:
quq_CCCP, да, я задумывался над прикреплением эффектов к пустым юнитам, сделаю в версии 2.1.
мб сделать параметр не ломать а отскакивать от блокиратора?
вскоре я сделаю так, чтобы от отскакивал обратно
Doc
You're doing it wrong.
неужели всё так плохо?
желательно тыкать меня носом)
Старый 19.05.2012, 15:56
Doc

offline
Опыт: 63,163
Активность:
Самое крупное, что заметил при беглом осмотре.
  1. При работе со снарядами полярки почти никогда не нужны. Тут они почти везде.
  2. Локейшены? Втф? Зачем? Бред.
Старый 19.05.2012, 16:04
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 14:31.