• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Collision System

LucasFerraz

Systems Analyst
Joined
Jun 10, 2010
Messages
2,858
Reaction score
96
Location
Brazil
Code:
Name: Collision System of Spells
Author: Ramza (Ricardo Ianelli)
Tested: TFS 0.3.6PL1

[video=youtube;uTvin2sLwu8]http://www.youtube.com/watch?feature=player_embedded&v=uTvin2sLwu8#at=28[/video]​

From the viewpoint of the player:
The player uses a spell, exori frigo. At the same time, the enemy uses a exori vis for example. Spells fly and collide in the air.

From the viewpoint of the scripter:
All spells before being casted, save a storage value, and check if enemy have the same storage. If yes , instead of sending the magic, the effects sends to a calculated position between two points, and an effect of collision.

How to install

colisionLIB.lua
Lua:
function checkColision(cid)   -- Function by Ramza (Ricardo Ianelli)
  if getCreatureTarget(cid) ~= 0 then
     setPlayerStorageValue(cid, 9001, 'casting')
     local ppos, enemy = getCreaturePosition(cid), getCreatureTarget(cid) 
     local epos = getCreaturePosition(enemy)

     if getPlayerStorageValue(enemy, 9001) == 'casting' and getCreatureTarget(enemy) == cid then
        setPlayerStorageValue(enemy, 9001, 'colision')
        setPlayerStorageValue(cid, 9001, 'colision')
        if ppos.x > epos.x and ppos.y > epos.y then
           cpos = {x = ppos.x - ((ppos.x - epos.x) / 2), y = ppos.y - ((ppos.y - epos.y) / 2), z = ppos.z}
        elseif ppos.x > epos.x and ppos.y < epos.y then
           cpos = {x = ppos.x - ((ppos.x - epos.x) / 2), y = epos.y - ((epos.y - ppos.y) / 2), z = ppos.z}
        elseif ppos.x < epos.x and ppos.y < epos.y then
           cpos = {x = epos.x - ((epos.x - ppos.x) / 2), y = epos.y - ((epos.y - ppos.y) / 2), z = ppos.z}
        elseif ppos.x < epos.x and ppos.y > epos.y then
           cpos = {x = epos.x - ((epos.x - ppos.x) / 2), y = ppos.y - ((ppos.y - epos.y) / 2), z = ppos.z}
        end
      
        doSendDistanceShoot(ppos, cpos, CONST_ANI_ENERGY)
        doSendDistanceShoot(epos, cpos, CONST_ANI_ENERGYBALL)
        
        local value = math.random(1, 3)
        doSendMagicEffect(cpos, 27+value)              
        return true
     else
        return false
     end
  end

end


Let's take a classic spell to example, this case exori vis.
Lua:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)
setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA)
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY)
setCombatFormula(combat, COMBAT_FORMULA_LEVELMAGIC, -1, -10, -1, -20, 5, 5, 1.4, 2.1)

function onCastSpell(cid, var)
	return doCombat(cid, combat, var)
end

You must change to this:
Lua:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE)
setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA)
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY)
setCombatFormula(combat, COMBAT_FORMULA_LEVELMAGIC, -1, -10, -1, -20, 5, 5, 1.4, 2.1)

local function spell(cid, var)
  if getPlayerStorageValue(cid, 9001) ~= 'colision' then
     doCreatureSay(cid, 'Strike!', TALKTYPE_ORANGE_1)
     return doCombat(cid, combat, var)
  end
end

function onCastSpell(cid, var)
	checkColision(cid)
	doCreatureSay(cid, 'Energy...', TALKTYPE_ORANGE_1)
	addEvent(spell, 2000, cid, var) 
end
 
Lol, Its a good start. But there is better ways to set things active. for example, You can do this with area spells also or directive spells ingeneral.

You have to do a global table:

Lua:
MAX_WIDTH = 65536
MAX_HEIGHT = 65536

TABLE_COLLISION = {
[0] = {},
[1] = {},
[2] = {},
[3] = {},
[4] = {},
[5] = {},
[6] = {},
[7] = {},
[8] = {},
[9] = {},
[10] = {},
[11] = {},
[12] = {},
[13] = {},
[14] = {},
[15] = {},
[16] = {},
[17] = {}}



function callback_setCollision(pos)
local index = (pos.y * MAX_WIDTH + pos.x)
local z = pos.z
local t = TABLE_COLLISION[z][index] or nil
if (t == nil) then
t = true -- You can set tile parameters here aswell, forexample damage type.
end
end

function callback_releasecollision(pos)
local index = (pos.y * MAX_WIDTH + pos.x)
local z = pos.z
local t = TABLE_COLLISION[z][index] or nil
if not(t == nil) then
t = nil
-- You can set a collision function here aswell.
else
return false
end
end

Itsnot finished. so i will try to finish it later. But yeah. basically what you do is to store the positions in a global table then set it to true/false for a time period before an addevent turns it to false again, this can be applied onTargetTile or onTargetCreature to interact between diffrent spells. like some fusion spells and so on.
 
Okey so this is going better than expected :3, If i am right, i should also be able to make any spell collide with both area and distance shots.
Which means that if you cross distance shots, they will both relocate to the crossing point and explode in the middle. ( Like explosion runes crossing each other)
If this is true, You can use UE or exori to shield again any spell for a certain amount of time( the spells duration).
This can also set up proper shielding spells that can block off certain elements or even cause then to do special effects(Running function onCollide)

Gotta download a server to try, Cause this would take PVP to a new level, where actuall timing is needed.

@elf Wanna help?, I need some kind of algorithm to deflect directional attacks, Kind of like casting ue behind a wall, Some look thingy so it cannot cast behind deflections.

I could use a line loop which checks every tile between two positions.
.. but that would be needed for every areatile in the combat, which means lag.
 
Nice idea. Usefull for something like "Harry potter Ots".
 
Okey so this is going better than expected :3, If i am right, i should also be able to make any spell collide with both area and distance shots.
Which means that if you cross distance shots, they will both relocate to the crossing point and explode in the middle. ( Like explosion runes crossing each other)
If this is true, You can use UE or exori to shield again any spell for a certain amount of time( the spells duration).
This can also set up proper shielding spells that can block off certain elements or even cause then to do special effects(Running function onCollide)

Gotta download a server to try, Cause this would take PVP to a new level, where actuall timing is needed.

@elf Wanna help?, I need some kind of algorithm to deflect directional attacks, Kind of like casting ue behind a wall, Some look thingy so it cannot cast behind deflections.

I could use a line loop which checks every tile between two positions.
.. but that would be needed for every areatile in the combat, which means lag.

If you show me what you've got we can make something better.
 
Lua:
MAX_WIDTH = 65536
MAX_HEIGHT = 65536
MAX_INTERSECTRADIUS = 6

TABLE_COLLISION = {
[0] = {},
[1] = {},
[2] = {},
[3] = {},
[4] = {},
[5] = {},
[6] = {},
[7] = {},
[8] = {},
[9] = {},
[10] = {},
[11] = {},
[12] = {},
[13] = {},
[14] = {},
[15] = {},
[16] = {},
[17] = {}}
 
CombatObject = {}
CombatObject.__index = CombatObject

CombatObject.create = function(tick, caster, position, element, onCollide)
	local combat = 
	{
	tick = tick or 500
	caster = caster or nil
	position = {x = position.x, y = position.y, z = position.z} -- creating a new table to prevent unknown editing.
	element = element
	onCollide = onCollide
	}
	setmetatable(combat, CombatObject)
	addEvent(function(comb) comb.remove() end, tick, combat)
	return combat
end

CombatObject.remove = function(ignoreOnCollide)
	if type(self.onCollide) == "function" and ignoreOnCollide == nil then
		self.onCollide(self.position, self.caster, self.element)
		self = nil
	end
	return nil
end 

CombatObject.checkCollisionLineLine = function(combat) -- Intersection between lines, gets position of collision also.
if isCreature(self.caster) then
local dx, dy, da, db,t,s = 0,0,0,0,0,0
local x1, y1 = getCreaturePosition(self.caster).x, getCreaturePosition(self.caster).y
local x2, y2 = self.position.x, self.position.y
    dx = x2 - x1
    dy = y2 - y1
    da = A2 - A1
    db = B2 - B1
    if (da * dy - db * dx) == 0 then
        return false
    end
    
    s = (dx * (B1 - y1) + dy * (x1 - A1)) / (da * dy - db * _
        dx)
    t = (da * (y1 - B1) + db * (A1 - x1)) / (db * dx - da * _
        dy)
    return s >= 0 and s <= 1 and t >= 0 and t <= 1
end
end

CombatObject.CheckCollision = function()
if not isCreature(self.caster) then
  self.remove()
  return false
end
local casterPosition = getCreaturePosition(self.caster)
local dx,dy = casterPosition.x - self.position.x, casterPosition.y - self.position.y
--division by 0, check so dx is not = 0
local k = dy/dx
  if (k > 0) and (dx > 0) then
  
  elseif (k < 0 and dx > 0) then
  elseif (k > 0 and dx < 0) then
  elseif (k < 0 and dx < 0) then
  elseif (k == 0 and (dx > 0 and dy = 0) then
  end
end
 
function callback_setCollision(pos, caster, element, tick, onCollide) --caster is for line intersecting.
	local index = (pos.y * MAX_WIDTH + pos.x)
	local z = pos.z
	local t = TABLE_COLLISION[z][index] or nil
	if (t == nil) then
		if caster ~= nil then
		t = CombatObject.create(tick, caster, position, element, onCollide) -- You can set tile parameters here aswell, forexample damage type.
		else
		return false
		end
	end
end -- No need to use two functions in callback, Using a class removes the need of twolines :3

Its far from complete, but you should get the hang of it.
What i want to do is to store a global table with a combat class which contains information about the combats active.
The class will automatically eliminate itself after a time period and execute an oncollide function.
how it check collision is like seeing, I use a KX+M formula (not completed yet due to negative values), where i check each tile in a line between two positions.
If it finds a combat object in the global table, it should return a position to everything. and execute things.

Im unclear of how that is gonna go. But i know that i will have to execute the oncollide script with an OnTargetTile, where you do the actuall combat inside doCombat.
 
MindRage. You are a scripting god.
Like for realz, you are very good.

Keep up the good work!
 
Elf and Mindrage, pretty good idea!
I'm Ricardo Ianelli (who created the collision system), maybe i can help you guys too with that xD
I wrote that code loooooooooong time ago (if you check the youtube video date you'll see) to a harry potter server i was creating, but i was noob :p
Maybe now i could help you guys (who are 100x better and more experienced than me) to create something new, if you want, ofc.
:D

---

Mindrage, i was reading your code and dude, you're awesome!
With that we could make colision reactions like energy+earth spells = non-dmg, resuming, could totally dominate the spells by another angle, a new angle :D

i never expected my noob code would make people do such great things :eek:
 
Last edited:
Its never the code quality, its the idea that matters ;3, The coding comes with the experience, Cause the more you want to do, the more you want to learn the ways you do it.
 
Looks great guys, seems like something I wouldn't mind using on a server of mine.
 
lucas, nao entendi direito a discussao, o script ta 100%? e só funciona com exori vis/exori frigo ou funciona com mort e tera tambem?
/
i didn't understand very good the discussion, is the script working 100%?
 
Yes alequis, it's working 100% but it's quite simple. Mindrage is trying to create an ultimate collision system with my idea xD
 
Back
Top