Hello Everyone,This is a spell that i have scripted.. it is good for some use but will need edits as it might somehow fuck up at any moment xD
Tested only on 0.3.7
but should work fine for 0.4
i dont script for tfs 1.2 unless there is a reason :3
Starting By Screenshots:
What so Special About This Script:
1-It Can have spells,your shadow clones will use your spells.. best 2-3 spells you can increase/decrease it
2-it uses your armor/Defense of shield and gear
3-It uses your weapon attack to precisely be like yourself
4-The monster have the same hp/skills/name just with an extra black skull.. the clone wont target you
5-The Clone can heal too and healing depends on your hp.. same for spells.. depends on your dmg and such
Now Time For the Scripts
First Source Edits:
Luascript.cpp:
add This
go to monster.h
Add This
Now monster.cpp
Replace
The Whole Function with this
creature.cpp
add This
Under
This should ensure the monsters wont attack you.. the shadow clones
Now lua part:
I Dont Support This Script / Fix it.. you are on your own.. you have to think of few things also for tip
there is a missing part in luascript.h but you can add it yourself.. it is easy
Healing is default and monster will heal randomly of 8% - 15%
Shadow Clones summons automatically with a target
Blocked Spell Uses name not word..
Tested only on 0.3.7
but should work fine for 0.4
i dont script for tfs 1.2 unless there is a reason :3
Starting By Screenshots:
What so Special About This Script:
1-It Can have spells,your shadow clones will use your spells.. best 2-3 spells you can increase/decrease it
2-it uses your armor/Defense of shield and gear
3-It uses your weapon attack to precisely be like yourself
4-The monster have the same hp/skills/name just with an extra black skull.. the clone wont target you
5-The Clone can heal too and healing depends on your hp.. same for spells.. depends on your dmg and such
Now Time For the Scripts
First Source Edits:
Luascript.cpp:
add This
Code:
int32_t LuaInterface::luaDoCreateCustomMonster(lua_State* L)
{
//doCreateCustomMonster(name, pos, outfit, health, attspell,defensespell,defense,armor,baseSpeed,exp,skull)
// created By MeNi for otland.net //
ScriptEnviroment* env = getEnv();
MonsterType* pobranyTyp = new MonsterType();
Monster* monster;
int64_t health, defense, armor, baseSpeed,experience;
Outfit_t outfit;
Skulls_t skull;
PositionEx pos;
skull = (Skulls_t)popNumber(L);
experience = popNumber(L);
baseSpeed = popNumber(L);
armor = popNumber(L);
defense = popNumber(L);
std::string defensespells = popString(L);
std::string attackspells = popString(L);
health = popNumber(L);
outfit = popOutfit(L);
popPosition(L, pos);
std::string name = popString(L);
pobranyTyp->spellAttackList.clear();
pobranyTyp->health = health;
pobranyTyp->healthMax = health;
pobranyTyp->outfit = outfit;
pobranyTyp->name = name;
pobranyTyp->nameDescription = name;
pobranyTyp->lookCorpse = 0;
pobranyTyp->targetDistance = 1;
pobranyTyp->experience = experience;
pobranyTyp->isSummonable = false;
pobranyTyp->isIllusionable = false;
pobranyTyp->isConvinceable = false;
pobranyTyp->isWalkable = true;
pobranyTyp->pushable = false;
pobranyTyp->isAttackable = true;
pobranyTyp->isHostile = true;
pobranyTyp->isConvinceable = true;
pobranyTyp->canPushItems = true;
pobranyTyp->canPushCreatures = true;
pobranyTyp->conditionImmunities |= CONDITION_PARALYZE;
pobranyTyp->conditionImmunities |= CONDITION_DRUNK;
pobranyTyp->conditionImmunities |= CONDITION_INVISIBLE;
pobranyTyp->defense = defense;
pobranyTyp->armor = armor;
pobranyTyp->skull = skull;
pobranyTyp->baseSpeed = baseSpeed;
pobranyTyp->changeTargetSpeed = 0;
pobranyTyp->changeTargetChance = 0;
if (!attackspells.empty()){
xmlNodePtr root_attack = xmlDocGetRootElement(xmlParseMemory(attackspells.c_str(), attackspells.length()));
xmlNodePtr tmpNode_attack = root_attack->children;
while (tmpNode_attack)
{
if (!xmlStrcmp(tmpNode_attack->name, (const xmlChar*)"attack"))
{
spellBlock_t sb;
if (g_monsters.deserializeSpell(tmpNode_attack, sb, "doCreateCustomMonster"))
pobranyTyp->spellAttackList.push_back(sb);
}
tmpNode_attack = tmpNode_attack->next;
}
}
if (!defensespells.empty()){
xmlNodePtr root_defense = xmlDocGetRootElement(xmlParseMemory(defensespells.c_str(), defensespells.length()));
xmlNodePtr tmpNode_defense = root_defense->children;
while (tmpNode_defense)
{
if (!xmlStrcmp(tmpNode_defense->name, (const xmlChar*)"defense"))
{
spellBlock_t defense;
if (g_monsters.deserializeSpell(tmpNode_defense, defense, "doCreateCustomMonster"))
pobranyTyp->spellDefenseList.push_back(defense);
}
tmpNode_defense = tmpNode_defense->next;
}
}
monster = Monster::createMonster(pobranyTyp);
if (!g_game.placeCreature(monster, pos, false, false))
{
delete monster;
lua_pushboolean(L, false);
return 1;
}
lua_pushnumber(L, env->addThing((Thing*)monster));
return 1;
}
Code:
//doCreateCustomMonster(....)
lua_register(m_luaState, "doCreateCustomMonster", LuaInterface::luaDoCreateCustomMonster);
go to monster.h
Add This
Code:
bool isClone(Creature* creature) { return creature && getName() == creature->getName() && getMonster() && getSkull() == SKULL_BLACK; }
Now monster.cpp
Replace
Code:
isTarget(Creature* creature)
The Whole Function with this
Code:
bool Monster::isTarget(Creature* creature)
{
return (!isClone(creature) && !creature->isRemoved() && creature->isAttackable() && creature->getZone() != ZONE_PROTECTION
&& canSeeCreature(creature) && creature->getPosition().z == getPosition().z) ;
}
creature.cpp
add This
Code:
if (creature && getName() == creature->getName() && getSkull() == SKULL_BLACK && getMonster())
return false;
Under
Code:
if(creature)
{
const Position& creaturePos = creature->getPosition();
if(creaturePos.z != getPosition().z || !canSee(creaturePos))
{
attackedCreature = NULL;
return false;
}
}
This should ensure the monsters wont attack you.. the shadow clones
Now lua part:
Code:
local config = {
HpBuff = 2.8, -- HpBuff * your max health
AttacksBuff = 3.0, -- att Buff * your Attack
DefenseBuff = 2.4, -- defense Buff * your defense
ArmorBuff = 2.1, -- same
SkillsBuff = 2.5, -- same
range = {5,5}, -- max x,y of range
blockedSpell = {'Light Healing','Shadow Clones','revive','Find Person','Light','Magic Rope','Cure Poison','Wound Cleansing'}, -- spells blocked in attack.. loop will jump it and goto next one
exhaustionTime = 300, -- time needed to recast spell
maxSpells = 10, -- max numbers of spells that boss can use
distance = 5, -- distance between you and player
maxChance = 25, -- chance for spells.. it is random 1-25
maxNumberOfCreatures = 4 -- max number of clones.
}
--[[ it is only 1 clone per creature..
]]
function getDef(cid)
local defense = 0
for i = CONST_SLOT_RIGHT,CONST_SLOT_LEFT do
if getPlayerSlotItem(cid, i).uid > 0 then
if getItemInfo(getPlayerSlotItem(cid,i).itemid).defense then
defense = defense + getItemInfo(getPlayerSlotItem(cid,i).itemid).defense
end
end
if getPlayerSlotItem(cid, i).uid > 0 then
if getItemInfo(getPlayerSlotItem(cid, i).itemid).extraDefense > 0 then
defense = defense + getItemInfo(getPlayerSlotItem(cid, i).itemid).extraDefense
end
end
end
return defense + getPlayerSkillLevel(cid, SKILL_SHIELD)
end
function getArm(cid)
local armor = 0
for i = CONST_SLOT_FIRST,CONST_SLOT_LAST do
if getPlayerSlotItem(cid, i).uid > 0 then
if getItemInfo(getPlayerSlotItem(cid,i).itemid).armor > 0 then
armor = armor + getItemInfo(getPlayerSlotItem(cid,i).itemid).armor
end
end
end
return armor > 0 and armor or 1
end
function getAtk(cid)
local weapon = getPlayerWeapon(cid)
local attack = 1
if weapon.uid > 0 then
if getItemInfo(weapon.itemid).attack then
attack = attack + getItemInfo(weapon.itemid).attack
end
if getItemInfo(weapon.itemid).extraAttack then
attack = attack + getItemInfo(weapon.itemid).extraAttack
end
end
return config.AttacksBuff*attack
end
function getSkill(cid)
if isSorcerer(cid) or isDruid(cid) then
return getPlayerMagLevel(cid) > 0 and getPlayerMagLevel(cid) or 1
elseif isPaladin(cid) then
return getPlayerSkillLevel(cid, SKILL_DISTANCE)
elseif isKnight(cid) then
local skills = {getPlayerSkillLevel(cid,SKILL_CLUB),getPlayerSkillLevel(cid,SKILL_SWORD),getPlayerSkillLevel(cid,SKILL_AXE)}
return getPlayerSkillLevel(cid, getHighestOfArray(skills))
else
return getPlayerSkillLevel(cid, SKILL_FIST)
end
return 1
end
function getHighestOfArray(ar)
table.sort(ar)
return ar[#ar]
end
function getStrongestSpells(cid, maximum)
local count = getPlayerInstantSpellCount(cid)
local t = {}
for i = 0, count - 1 do
local spell = getPlayerInstantSpellInfo(cid, i)
table.insert(t, spell)
end
table.sort(t, function(a, b) return a.level < b.level end)
local spellsNames = {}
local counter = 0
local i = 0
while(counter < maximum) do
if not isInArray(config.blockedSpell,t[#t-i].name) then
table.insert(spellsNames,t[#t-i].name)
counter = counter + 1
end
i = i + 1
if((#t - i) <= 0)then
break
end
end
return spellsNames
end
--Dont Touch this
function setAttack(cid)
math.randomseed(os.time())
local attacks = "<a>"
attacks = attacks .. '<attack name="melee" interval="1000" chance="100" skill="'..config.SkillsBuff*getSkill(cid)..'" attack="'..getAtk(cid)..'" radius="1" target="1"/>'
local spells = getStrongestSpells(cid, config.maxSpells)
if(#spells > 0)then
for i = 1,#spells do
local words = '<attack name="replaceThis" interval="'..math.random(1000,8000)..'" chance="'..math.random(1,config.maxChance)..'"/>'
local text = string.gsub(words,"replaceThis",spells[i])
attacks = attacks .. text
end
end
attacks = attacks .. "</a>"
return attacks
end
--Dont Touch this
function setDefense(c,s)
local defenses = "<s>"
for i=1,#c do
defenses = defenses .. c[i].text
end
defenses = defenses .. "</s>"
return defenses
end
function summonClones(cid, center,targetPlayer)
local sp = {
defenses = {
[1] = {text = '<defense name="healing" interval="1000" chance="'..math.random(8,20)..'" min="'..(math.floor(getCreatureMaxHealth(cid) * 0.08))..'" max="'..(math.floor(getCreatureMaxHealth(cid) * 0.15))..'"><attribute key="areaEffect" value="blueshimmer"/></defense>'},
}
}
doSendMagicEffect(center,CONST_ME_TELEPORT)
local monster = doCreateCustomMonster(getCreatureName(cid),center,getCreatureOutfit(cid),config.HpBuff*getCreatureMaxHealth(cid),setAttack(cid),setDefense(sp.defenses,c),config.DefenseBuff*getDef(cid),config.ArmorBuff*getArm(cid),getCreatureSpeed(cid),0, SKULL_BLACK)
doMonsterSetTarget(monster, targetPlayer)
return true
end
function onCastSpell(cid, var)
if exhaustion.check(cid, 50062) then
doPlayerSendCancel(cid, "You Are Still Collecting Your Power.. Time Left:"..(math.floor(exhaustion.get(cid,50062) / 60) >= 1 and ""..math.floor(exhaustion.get(cid,50062) / 60).." Minutes." or ""..math.floor((exhaustion.get(cid,50062) % 60)).." Seconds.")..".")
doSendMagicEffect(getThingPos(cid),CONST_ME_POFF)
return false
end
local spec = getSpectators(getThingPos(cid), config.range[1], config.range[2])
if #spec > 0 then
for i = 1,math.min(config.maxNumberOfCreatures+1,#spec) do
if getDistanceBetween(getThingPos(cid), getThingPos(spec[i])) <= config.distance and getCreatureName(spec[i]) ~= getCreatureName(cid)
and isSightClear(getThingPos(cid), getThingPos(spec[i]), false) and not isNpc(spec[i]) and not getTileInfo(getThingPos(spec[i])).protection then
summonClones(cid, getClosestFreeTile(cid, getThingPos(spec[i])),spec[i])
doSendDistanceShoot(getThingPos(cid), getThingPos(spec[i]), math.random(1,40))
end
end
exhaustion.set(cid, 50062, config.exhaustionTime)
end
return true
end
I Dont Support This Script / Fix it.. you are on your own.. you have to think of few things also for tip
there is a missing part in luascript.h but you can add it yourself.. it is easy
Healing is default and monster will heal randomly of 8% - 15%
Shadow Clones summons automatically with a target
Blocked Spell Uses name not word..
Last edited: