From: <ral...@us...> - 2014-04-18 22:45:32
|
Revision: 9456 http://sourceforge.net/p/planeshift/code/9456 Author: ralphcampbell Date: 2014-04-18 22:45:28 +0000 (Fri, 18 Apr 2014) Log Message: ----------- Ranged weapons that are themselves the ammo, now work. Just mark them as ROCK in item_stats.item_type. This can be used for javelin, spears, throwing stars, etc. If item_stats.valid_slots is 'BOTHHANDS', it can only be equipped if both hands are empty. This also results in only one attack per cycle. More changes to attacks and attack_type tables to allow future growth. Bumped database version to 1278 and updated upgrade_schema.sql. RelatedStatID is defined instead of RelatedStat in attacks.damage script. Added AttackID and AttackTypeID. attackType is now the ID rather than the name of the attack_type table entry. Fixed AOE combat attacks so they don't affect the attacker. Modified Paths: -------------- trunk/src/server/bulkobjects/psattack.cpp trunk/src/server/bulkobjects/psattack.h trunk/src/server/bulkobjects/pscharinventory.cpp trunk/src/server/bulkobjects/psitem.h trunk/src/server/bulkobjects/psitemstats.cpp trunk/src/server/bulkobjects/psitemstats.h trunk/src/server/bulkobjects/psquestprereqops.cpp trunk/src/server/database/mysql/attack_types.sql trunk/src/server/database/mysql/attacks.sql trunk/src/server/database/mysql/item_stats.sql trunk/src/server/database/mysql/math_scripts.sql trunk/src/server/database/mysql/progress_events.sql trunk/src/server/database/mysql/server_options.sql trunk/src/server/database/mysql/upgrade_schema.sql trunk/src/server/psserver.cpp Modified: trunk/src/server/bulkobjects/psattack.cpp =================================================================== --- trunk/src/server/bulkobjects/psattack.cpp 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psattack.cpp 2014-04-18 22:45:28 UTC (rev 9456) @@ -57,6 +57,7 @@ /**********************************************************************************************************/ psAttack::psAttack() : + attackDelay(0), attackRange(0), aoeRadius(0), aoeAngle(0) @@ -65,6 +66,7 @@ psAttack::~psAttack() { + delete attackDelay; delete attackRange; delete aoeRadius; delete aoeAngle; @@ -80,12 +82,13 @@ MathScriptEngine* mse = psserver->GetMathScriptEngine(); damage_script = mse->FindScript(row["damage"]); - attackDelay = mse->FindScript(row["delay"]); - if(!damage_script || !attackDelay) + if(!damage_script) return false; - type = psserver->GetCacheManager()->GetAttackTypeByName(row["attackType"]); + unsigned id = atoi(row["attackType"]); + type = psserver->GetCacheManager()->GetAttackTypeByID(id); + attackDelay = MathExpression::Create(row["delay"], "attackDelay"); attackRange = MathExpression::Create(row["range"], "attackRange"); aoeRadius = MathExpression::Create(row["aoe_radius"], "aoeRadius"); aoeAngle = MathExpression::Create(row["aoe_angle"], "aoeAngle"); @@ -120,7 +123,6 @@ { psCharacter* character = attacker->GetCharacterData(); psItem* weapon = character->Inventory().GetEffectiveWeaponInSlot(slot); - float latency = weapon->GetLatency(); float dist; { @@ -140,15 +142,21 @@ dist = sqrtf(csSquaredDist::PointPoint(targetPos, attackerPos)); } - MathEnvironment env; - env.Define("Latency", latency); - env.Define("Distance", dist); - attackDelay->Evaluate(&env); - MathVar* result = env.Lookup("Result"); - csTicks delay = (csTicks)result->GetRoundValue(); + psCombatAttackGameEvent* event = + new psCombatAttackGameEvent(0, this, attacker, target, slot, weapon); + MathEnvironment& env(event->env); + env.Define("AttackID", id); + env.Define("AttackTypeID", type ? type->id : 0); + env.Define("Attacker", attacker); + env.Define("Target", target); + env.Define("OrigTarget", target); + env.Define("AttackSlot", slot); + env.Define("AttackWeapon", weapon); + env.Define("RelatedStatID", type ? type->related_stat : 0); + env.Define("Distance", dist); + csTicks delay = attackDelay ? (csTicks)round(attackDelay->Evaluate(&env)) : 0; + event->triggerticks = csGetTicks() + delay; - psCombatAttackGameEvent* event = - new psCombatAttackGameEvent(delay, this, attacker, target, slot, weapon); character->TagEquipmentObject(slot, event->id); psserver->GetEventManager()->Push(event); @@ -242,7 +250,8 @@ } else { - // Check if the npc's target has changed (if it has, then assume another combat event has started.) + // Check if the npc's target has changed. + // If it has, then assume another combat event has started. gemNPC* npcAttacker = attacker->GetNPCPtr(); if(npcAttacker && npcAttacker->GetTarget() != target) { @@ -271,8 +280,15 @@ event->GetWeaponSlot() == PSCHARACTER_SLOT_RIGHTHAND ? PSCHARACTER_SLOT_LEFTHAND: PSCHARACTER_SLOT_RIGHTHAND; psItem* otherItem = attacker_data->Inventory().GetInventoryItem(otherHand); - if(otherItem == NULL) + uint32_t item_id = 0; + if(weapon->GetAmmoType() == PSITEMSTATS_AMMOTYPE_ROCKS) { + // Rocks are their own ammo. + attack_result = ATTACK_NOTCALCULATED; + item_id = weapon->GetUID(); + } + else if(otherItem == NULL) + { attack_result = ATTACK_OUTOFAMMO; } else if(otherItem->GetIsContainer()) // Is it a quiver? @@ -284,23 +300,29 @@ { psItem* currItem = attacker_data->Inventory().GetInventoryIndexItem(i); if(currItem && - currItem->GetContainerID() == otherItem->GetUID() && - weapon->GetAmmoTypeID().In(currItem->GetBaseStats()->GetUID())) + currItem->GetContainerID() == item_id && + weapon->UsesAmmoType(currItem->GetBaseStats()->GetUID())) { otherItem = currItem; attack_result = ATTACK_NOTCALCULATED; + item_id = otherItem->GetUID(); break; } } } - else if(!weapon->GetAmmoTypeID().In(otherItem->GetBaseStats()->GetUID())) + else if(!weapon->UsesAmmoType(otherItem->GetBaseStats()->GetUID())) { attack_result = ATTACK_OUTOFAMMO; } + else + { + attack_result = ATTACK_NOTCALCULATED; + item_id = otherItem->GetUID(); + } if(attack_result != ATTACK_OUTOFAMMO) { - psItem* usedAmmo = attacker_data->Inventory().RemoveItemID(otherItem->GetUID(), 1); + psItem* usedAmmo = attacker_data->Inventory().RemoveItemID(item_id, 1); if(usedAmmo) { attack_result = CalculateAttack(event, usedAmmo); @@ -316,15 +338,11 @@ attack_result = CalculateAttack(event); } - int affectedCount = 0; + int affectedCount = 1; + AffectTarget(target, event, attack_result); float radius = aoeRadius ? aoeRadius->Evaluate(&event->env) : 0.0; - if(radius < 0.01f) // single target + if(radius >= 0.01f) // AOE (Area of Effect) { - AffectTarget(target, event, attack_result); - affectedCount++; - } - else // AOE (Area of Effect) - { csVector3 attackerPos; csVector3 targetPos; iSector* attackerSector, *targetSector; @@ -346,6 +364,9 @@ for(size_t i = 0; i < nearby.GetSize(); i++) { gemActor* nearby_target = nearby[i]->GetActorPtr(); + if(nearby_target == attacker || nearby_target == target) + continue; + csString msg; if(!attacker->IsAllowedToAttack(nearby_target, msg)) continue; @@ -379,18 +400,10 @@ AffectTarget(nearby_target, event, attack_result); affectedCount++; } - - if(affectedCount > 0) - { - psserver->SendSystemInfo(attacker->GetClientID(), - "%s affected %d %s.", - name.GetData(), affectedCount, - (affectedCount == 1) ? "target" : "targets"); - } - else - { - psserver->SendSystemInfo(attacker->GetClientID(), "%s has no effect.", name.GetData()); - } + psserver->SendSystemInfo(attacker->GetClientID(), + "%s affected %d %s.", + name.GetData(), affectedCount, + (affectedCount == 1) ? "target" : "targets"); } // Get the next special attack to execute. @@ -415,7 +428,6 @@ gemActor* attacker = event->GetAttacker(); gemActor* target = event->GetTarget(); - psCharacter* attacker_data = attacker->GetCharacterData(); psCharacter* target_data = target->GetCharacterData(); // calculate difference between target and attacker location - to be used for angle validation @@ -438,10 +450,6 @@ } MathEnvironment& env(event->env); - env.Define("Attacker", attacker); - env.Define("Target", target); - env.Define("OrigTarget", target); - env.Define("AttackWeapon", event->GetWeapon()); env.Define("AttackWeaponSecondary", subWeapon); env.Define("TargetWeapon", target_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot(), true)); env.Define("TargetWeaponSecondary", target_data->Inventory().GetEffectiveWeaponInSlot(otherHand, true)); @@ -449,8 +457,6 @@ env.Define("DiffX", diff.x ? diff.x : 0.00001F); // force minimal value env.Define("DiffY", diff.y ? diff.y : 0.00001F); // force minimal value env.Define("DiffZ", diff.z ? diff.z : 0.00001F); // force minimal value - env.Define("RelatedStat", type ? - attacker_data->GetSkillRank(type->related_stat).Current() : 0); float range = attackRange ? attackRange->Evaluate(&env) : 0.0; env.Define("Range", range); @@ -646,20 +652,12 @@ } case ATTACK_OUTOFRANGE: { - if(event->GetAttackerID()) - { - psserver->SendSystemError(event->GetAttackerID(),"You are too far away to attack!"); - - } + psserver->SendSystemError(event->GetAttackerID(),"You are too far away to attack!"); break; } case ATTACK_BADANGLE: { - if(event->GetAttackerID()) // if human player - { - psserver->SendSystemError(event->GetAttackerID(),"You must face the enemy to attack!"); - - } + psserver->SendSystemError(event->GetAttackerID(),"You must face the enemy to attack!"); break; } case ATTACK_OUTOFAMMO: Modified: trunk/src/server/bulkobjects/psattack.h =================================================================== --- trunk/src/server/bulkobjects/psattack.h 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psattack.h 2014-04-18 22:45:28 UTC (rev 9456) @@ -157,7 +157,7 @@ csRef<psQuestPrereqOp> TypeRequirements; ///< all Attack Type based requirements(not handled as a script) /// Delay in milliseconds before attack "hits" or has an effect. - MathScript* attackDelay; + MathExpression* attackDelay; /// The Max Range of the attack (Meters) MathExpression* attackRange; /// AOE Radius: (Power, WaySkill, RelatedStat) -> Meters Modified: trunk/src/server/bulkobjects/pscharinventory.cpp =================================================================== --- trunk/src/server/bulkobjects/pscharinventory.cpp 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/pscharinventory.cpp 2014-04-18 22:45:28 UTC (rev 9456) @@ -540,6 +540,22 @@ // It needs to fit in that slot if(!item->FitsInSlot(proposedSlot)) return false; + // If item requires both hands, make sure other hand is empty. + // Otherwise, make sure other hand doesn't require both hands. + INVENTORY_SLOT_NUMBER otherSlot = + proposedSlot == PSCHARACTER_SLOT_RIGHTHAND ? + PSCHARACTER_SLOT_LEFTHAND : PSCHARACTER_SLOT_RIGHTHAND; + if(item->FitsInSlot(PSCHARACTER_SLOT_BOTHHANDS)) + { + if(GetInventoryItem(otherSlot)) + return false; + } + else + { + psItem *other = GetInventoryItem(otherSlot); + if(other && other->FitsInSlot(PSCHARACTER_SLOT_BOTHHANDS)) + return false; + } // It better not be a stack (unless explicitly allowed) if(stackCount > 1 && !item->GetIsEquipStackable()) return false; @@ -623,16 +639,25 @@ INVENTORY_SLOT_NUMBER psCharacterInventory::FindFreeEquipSlot(psItem* itemToPlace) { - csArray<INVENTORY_SLOT_NUMBER> fitsIn; + const csArray<INVENTORY_SLOT_NUMBER>& fitsIn(itemToPlace->GetBaseStats()->GetSlots()); + bool bothhands = itemToPlace->FitsInSlot(PSCHARACTER_SLOT_BOTHHANDS); - fitsIn = itemToPlace->GetBaseStats()->GetSlots(); - for(size_t i = 0; i < fitsIn.GetSize(); i++) { INVENTORY_SLOT_NUMBER proposedSlot = fitsIn[i]; psItem* existingItem = GetInventoryItem(proposedSlot); // If there is an item already here then this is not allowed for equipment. - if(!existingItem && itemToPlace->FitsInSlots(psserver->GetCacheManager()->slotMap[proposedSlot])) + if(existingItem) + continue; + if(bothhands) + { + INVENTORY_SLOT_NUMBER otherSlot = + proposedSlot == PSCHARACTER_SLOT_RIGHTHAND ? + PSCHARACTER_SLOT_LEFTHAND : PSCHARACTER_SLOT_RIGHTHAND; + if(!GetInventoryItem(otherSlot)) + return proposedSlot; + } + else if(itemToPlace->FitsInSlots(psserver->GetCacheManager()->slotMap[proposedSlot])) return proposedSlot; } return PSCHARACTER_SLOT_NONE; @@ -997,7 +1022,10 @@ if(!item) { item = GetInventoryItem(PSCHARACTER_SLOT_LEFTHAND); - + if(!item) + { + item = GetInventoryItem(PSCHARACTER_SLOT_BOTHHANDS); + } } return item; @@ -1233,13 +1261,13 @@ if(slot<0 || slot>=PSCHARACTER_SLOT_BULK1) return false; - // The autoattack or singleattack flags must be set if((equipment[slot].EquipmentFlags & PSCHARACTER_EQUIPMENTFLAG_AUTOATTACK) || - (equipment[slot].EquipmentFlags & PSCHARACTER_EQUIPMENTFLAG_SINGLEATTACK)) + (equipment[slot].EquipmentFlags & PSCHARACTER_EQUIPMENTFLAG_SINGLEATTACK)) { // Check if the slot is empty and can attack when empty - if(equipment[slot].itemIndexEquipped==0 && (equipment[slot].EquipmentFlags & PSCHARACTER_EQUIPMENTFLAG_ATTACKIFEMPTY)) + if(equipment[slot].itemIndexEquipped==0 && + (equipment[slot].EquipmentFlags & PSCHARACTER_EQUIPMENTFLAG_ATTACKIFEMPTY)) { return true; } @@ -1248,14 +1276,10 @@ if(equipment[slot].itemIndexEquipped==0) return false; - // If the item is a melee weapon, it's OK - if(inventory[equipment[slot].itemIndexEquipped].item->GetIsMeleeWeapon()) + // If the item is a melee or ranged weapon, it's OK. + psItem* item = inventory[equipment[slot].itemIndexEquipped].item; + if(item->GetIsMeleeWeapon() || item->GetIsRangeWeapon()) return true; - - if(inventory[equipment[slot].itemIndexEquipped].item->GetIsRangeWeapon()) - { - return true; - } } return false; Modified: trunk/src/server/bulkobjects/psitem.h =================================================================== --- trunk/src/server/bulkobjects/psitem.h 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psitem.h 2014-04-18 22:45:28 UTC (rev 9456) @@ -830,9 +830,9 @@ { return current_stats->GetRange(); } - csSet<unsigned int> GetAmmoTypeID() const + bool UsesAmmoType(uint32_t id) const { - return current_stats->GetAmmoTypeID(); + return current_stats->UsesAmmoType(id); } psWeaponType *GetWeaponType(); Modified: trunk/src/server/bulkobjects/psitemstats.cpp =================================================================== --- trunk/src/server/bulkobjects/psitemstats.cpp 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psitemstats.cpp 2014-04-18 22:45:28 UTC (rev 9456) @@ -817,8 +817,10 @@ } else if(currentSlot == "BOTHHANDS") { - valid_slots|=PSITEMSTATS_SLOT_BOTHHANDS; - valid_slots_array.Push(PSCHARACTER_SLOT_BOTHHANDS); + valid_slots_array.Push(PSCHARACTER_SLOT_RIGHTHAND); + valid_slots_array.Push(PSCHARACTER_SLOT_LEFTHAND); + valid_slots |= PSITEMSTATS_SLOT_RIGHTHAND | + PSITEMSTATS_SLOT_LEFTHAND | PSITEMSTATS_SLOT_BOTHHANDS; } else if(currentSlot == "HELM") { Modified: trunk/src/server/bulkobjects/psitemstats.h =================================================================== --- trunk/src/server/bulkobjects/psitemstats.h 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psitemstats.h 2014-04-18 22:45:28 UTC (rev 9456) @@ -661,9 +661,9 @@ bool GetBuyPersonalise(); float GetRange() const; PID GetCreator(PSITEMSTATS_CREATORSTATUS &creatorStatus); - csSet<unsigned int> GetAmmoTypeID() const + bool UsesAmmoType(uint32_t id) const { - return ammo_types; + return ammo_types.In(id); } float weaponRange; @@ -805,7 +805,7 @@ psMoney &GetPrice(); void SetCategory(psItemCategory* category); psItemCategory* GetCategory(); - csArray<INVENTORY_SLOT_NUMBER> GetSlots() + const csArray<INVENTORY_SLOT_NUMBER>& GetSlots() const { return valid_slots_array; } Modified: trunk/src/server/bulkobjects/psquestprereqops.cpp =================================================================== --- trunk/src/server/bulkobjects/psquestprereqops.cpp 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/bulkobjects/psquestprereqops.cpp 2014-04-18 22:45:28 UTC (rev 9456) @@ -821,7 +821,7 @@ { if (character->Inventory().CanItemAttack((INVENTORY_SLOT_NUMBER) slot)) { - return checkWeapon(character,slot); + return checkWeapon(character, slot); } } @@ -839,29 +839,25 @@ return false; } } - if(!checkWType(character,weapon)) - return false; + return checkWType(character, weapon); +} - return true; -} bool psPrereqOpAttackType::checkWType(psCharacter* character, psItem* weapon) { if(!attackType->weaponTypes.IsEmpty()) { - bool checkFlag = false; for(size_t i = 0; i < attackType->weaponTypes.GetSize(); i++) { if(attackType->weaponTypes[i] == weapon->GetWeaponType()) { - checkFlag = true; + return true; } } - if(checkFlag != true) - return false; + return false; } - return true; } + csString psPrereqOpAttackType::GetScriptOp() { csString script = "<>"; Modified: trunk/src/server/database/mysql/attack_types.sql =================================================================== --- trunk/src/server/database/mysql/attack_types.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/attack_types.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -5,8 +5,8 @@ CREATE TABLE `attack_types` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'holds the attack type unique id number' , `name` VARCHAR(40) NOT NULL COMMENT 'is the attack type name, each name must be unique.' , - `weaponName` VARCHAR(40) DEFAULT NULL COMMENT 'filled in for a very specific weapon with special attack, either this or weapon type should always be filled in', - `weaponType` VARCHAR(40) DEFAULT NULL COMMENT 'more than one required weapon type may be listed, seperate each weapon type id with a space', + `weaponName` VARCHAR(60) DEFAULT NULL COMMENT 'filled in for a very specific weapon with special attack, either this or weapon type should always be filled in', + `weaponType` VARCHAR(100) DEFAULT NULL COMMENT 'more than one required weapon type may be listed. Separate each weapon type with a space', `onehand` BOOLEAN NOT NULL COMMENT 'attack designed for a 1 hand weapon (true) or 2 handed (false)', `stat` int(11) NOT NULL COMMENT 'The skill related to this type', PRIMARY KEY (`id`) , Modified: trunk/src/server/database/mysql/attacks.sql =================================================================== --- trunk/src/server/database/mysql/attacks.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/attacks.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -9,19 +9,19 @@ `attack_anim` VARCHAR(40) COMMENT 'The visual effect of the attack', `attack_description` text COMMENT 'a short description of the attack', `damage` VARCHAR(40) COMMENT 'A math script to compute the chance of success and final damage. Variables defined here can be used in the range, aoe_radius, and aoe_angle MathExpressions.', - `attackType` VARCHAR(40) NOT NULL COMMENT 'the type of attack it is, found in the attack_types table', - `delay` VARCHAR(40) COMMENT 'A math script to compute the time before the attack starts (based on latency of weapon, range, attack speed, ...)', + `attackType` INT NOT NULL COMMENT 'the ID of the type of attack, found in the attack_types table', + `delay` text COMMENT 'A MathExpression to compute the time before the attack starts (based on latency of weapon, range, attack speed, ...)', `range` text COMMENT 'Mostly for range attacks, melee is confined based on weapon range', - `aoe_radius` text COMMENT 'This is the radius, can be a formula or a solid number, of the aoe attack', - `aoe_angle` text COMMENT 'The angle in front of the player the aoe attack will affect, 0 for no aoe, 1-360 for aoe, can also be a formula', - `outcome` VARCHAR(40) NOT NULL COMMENT 'The effect, in a progression script, of the attack', + `aoe_radius` text COMMENT 'This is the radius of the aoe attack. It can be a formula or a number; 0 for no aoe', + `aoe_angle` text COMMENT 'The angle in front of the player the aoe attack will affect, 1-360 degrees and can also be a formula', + `outcome` VARCHAR(40) NOT NULL COMMENT 'The effect, a progression script, of the attack', `requirements` VARCHAR(250) NULL DEFAULT '<pre></pre>' COMMENT 'is a xml script of requirements, these requirements will be checked before a character can use the attack. schema to be added soon, but will be very flexable.' , PRIMARY KEY (`id`) , UNIQUE INDEX `name_UNIQUE` (`name`) ) COMMENT='Holds attacks'; -- The first entry (id 1) must be the default attack. -INSERT INTO `attacks` VALUES (1, 'default', '', 'hit', 'a normal attack', 'Calculate Damage', '', 'AttackDefaultDelay', NULL, '0', '', '', ''); -INSERT INTO `attacks` VALUES (2, 'Hammer Smash', '/planeshift/materials/club01a_icon.dds', 'hit', 'an attack that causes a hammer to smash the ground and damage all nearby targets', 'Calculate Damage', 'Barbaric', 'AttackDefaultDelay', NULL, '20', '360', 'cast Hammer Smash', ''); -INSERT INTO `attacks` VALUES (3, 'Hyper Shot', '/planeshift/materials/bow_higher01a_icon.dds', 'hit', 'A very powerful bow attack', 'Calculate Damage', 'Archery', 'AttackRangeDelay', '60', '0', '0', 'cast Hyper Shot', '<pre> <skill name=\"ranged\" min=\"50\" max=\"4000\" /> </pre>'); -INSERT INTO `attacks` VALUES (4, 'Divine Shot', '/planeshift/materials/bow_higher01a_icon.dds', 'hit', 'A long bow specific shot that takes the power of the gods and pushes it into an arrow', 'Calculate Damage', 'Long Bow Special', 'AttackRangeDelay', '100', '50', '90', 'cast LB Shot', ''); +INSERT INTO `attacks` VALUES (1, 'default', '', 'hit', 'a normal attack', 'Calculate Damage', 0, 'AttackWeapon:Latency * 1000', NULL, '0', '', '', ''); +INSERT INTO `attacks` VALUES (2, 'Hammer Smash', '/planeshift/materials/club01a_icon.dds', 'hit', 'an attack that causes a hammer to smash the ground and damage all nearby targets', 'Calculate Damage', 3, 'AttackWeapon:Latency * 1000', NULL, '20', '360', 'cast Hammer Smash', ''); +INSERT INTO `attacks` VALUES (3, 'Hyper Shot', '/planeshift/materials/bow_higher01a_icon.dds', 'hit', 'A very powerful bow attack', 'Calculate Damage', 2, 'AttackWeapon:Latency * 1000 + Distance * 100', '60', '0', '0', 'cast Hyper Shot', '<pre> <skill name=\"ranged\" min=\"50\" max=\"4000\" /> </pre>'); +INSERT INTO `attacks` VALUES (4, 'Divine Shot', '/planeshift/materials/bow_higher01a_icon.dds', 'hit', 'A long bow specific shot that takes the power of the gods and pushes it into an arrow', 'Calculate Damage', 4, 'AttackWeapon:Latency * 1000 + Distance * 100', '100', '50', '90', 'cast LB Shot', ''); Modified: trunk/src/server/database/mysql/item_stats.sql =================================================================== --- trunk/src/server/database/mysql/item_stats.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/item_stats.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -103,7 +103,7 @@ INSERT INTO `item_stats` VALUES (2,'B','Small Battle Axe',5.00,5.00,100,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,2,-1,-1,'0','0','0',0.00,0.00,0.00,5.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#doubleaxe01a','/planeshift/weapons/doubleaxe01a_icon.dds','','','','','Axe',1,350.00,'AXE','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','smallaxe',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (3,'B','Battle Axe',10.00,5.00,150,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,2,-1,-1,'0','0','0',0.00,0.00,0.00,5.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#doubleaxe02a','/planeshift/weapons/doubleaxe02a_icon.dds','','','','','Axe',1,650.00,'AXE','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (4,'B','Broad Sword',7.00,5.00,100,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,6.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#broadsword01a','/planeshift/weapons/broadsword01a_icon.dds','','','','','Sabre',1,150.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,2,"",'Y'); -INSERT INTO `item_stats` VALUES (5,'B','Claymore',9.00,5.00,120,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,8.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#claymore01a','/planeshift/weapons/claymore01a_icon.dds','','','','','Claymore',1,800.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,5,"",'Y'); +INSERT INTO `item_stats` VALUES (5,'B','Claymore',9.00,5.00,120,0,0,'BULK BOTHHANDS','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,8.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#claymore01a','/planeshift/weapons/claymore01a_icon.dds','','','','','Claymore',1,800.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,5,"",'Y'); INSERT INTO `item_stats` VALUES (6,'B','Gold Falchion',8.00,5.00,80,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,9.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#falchion01a','/planeshift/weapons/falchion01a_icon.dds','','','','','Sabre',1,550.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (7,'B','Falchion',7.00,5.00,80,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#falchion01b','/planeshift/weapons/falchion01b_icon.dds','','','','','Sabre',1,500.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (8,'B','Steel Falchion',6.50,5.00,80,0,0,'BULK LEFTHAND RIGHTHAND','MELEEWEAPON STACKABLE',0.10,0,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,0.00,0.00,4.00,2.00,0.20,0.20,0.20,0.00,'weapons#falchion01c','/planeshift/weapons/falchion01c_icon.dds','','','','','Sabre',1,450.00,'SWORD','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'0','nosound',50,'',NULL,NULL,-1,2,"",'Y'); @@ -253,6 +253,7 @@ INSERT INTO `item_stats` VALUES (234,'B','Book Container',1.00,100.00,1,20,16,'BULK','CONTAINER',0.10,-1,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,1.00,0.00,2.10,1.00,0.20,0.20,0.20,0.00,'potions#potion01a','/planeshift/potions/smallpotion01a_icon.dds','','','','','0',3,4.00,'GENERIC','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'A Book Container','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (235,'B','Sack',1.00,100.00,1,20,16,'BULK','CONTAINER',0.10,-1,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,1.00,0.00,2.10,1.00,0.20,0.20,0.20,0.00,'potions#potion01a','/planeshift/potions/smallpotion01a_icon.dds','','','','','0',3,4.00,'GENERIC','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'A Sack','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (319,'B','Iron Stock',3.00,100.00,5,0,0,'BULK LEFTHAND RIGHTHAND','STACKABLE',0.10,4,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,1.00,0.00,2.10,1.00,0.20,0.20,0.20,0.00,'potions#potion01a','/planeshift/potions/smallpotion01a_icon.dds','','','','','0',16,10.00,'','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'Long metal bars of iron used in smiting.','nosound',50,'',NULL,NULL,-1,2,"",'Y'); +INSERT INTO `item_stats` VALUES (407,'B','Throwing Stone',0.1,100.00,1,1,0,'BULK RIGHTHAND LEFTHAND','RANGEWEAPON USESAMMO AMMO STACKABLE EQUIP_STACKABLE',0.10,-1,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,1.60,0.00,0.00,0.00,0.00,0.00,0.00,0.00,'weapons#doubleaxe01a','/planeshift/weapons/doubleaxe01a_icon.dds','/planeshift/weapons/doubleaxe01a_icon.dds','','','','Arrow',1,0.00,'ROCK',NULL,0.00,NULL,0.00,NULL,0.00,'0',NULL,0.0000,NULL,0,NULL,0,'Small rock for throwing.','nosound',50,NULL,NULL,NULL,-1,20,"",'Y'); INSERT INTO `item_stats` VALUES (408,'B','basecloths',1.00,100.00,1,0,0,'ARMS BOOTS GLOVES HELM TORSO LEGS','ARMOR',0.10,7,-1,-1,'0','0','0',0.00,0.00,0.00,1.00,1.00,1.00,1.00,0.00,0.00,0.00,0.00,0.00,'','','','','','','0',2,0.00,'ARMOR','',0.00,'',0.00,'',0.00,'0',0,0.0000,0,0,0,1,'Clothes used in combat when no other armor is available','nosound',50,'',NULL,NULL,-1,2,"",'Y'); INSERT INTO `item_stats` VALUES (409,'B','Long Bow',2.00,100.00,1,5,0,'BULK RIGHTHAND LEFTHAND','RANGEWEAPON USESAMMO',0.10,6,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,0.00,9.00,2.00,7.00,0.00,0.00,0.00,0.00,'weapons#doubleaxe01a','/planeshift/weapons/doubleaxe01a_icon.dds','/planeshift/weapons/doubleaxe01a_icon.dds','','','','Stick',1,25.00,'BOW','',0.00,'',0.00,'',0.00,'410',0,0.0000,0,0,0,1,'A long bow of normal quality. Common among rangers and is reputed for its long range.','nosound',50,'',NULL,NULL,-1,20,"",'Y'); INSERT INTO `item_stats` VALUES (410,'B','Bronze Arrow',0.25,100.00,1,1,0,'BULK RIGHTHAND LEFTHAND','AMMO STACKABLE EQUIP_STACKABLE',0.10,-1,-1,-1,'0','0','0',0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,'weapons#doubleaxe01a','/planeshift/weapons/doubleaxe01a_icon.dds','/planeshift/weapons/doubleaxe01a_icon.dds','','','','Arrow',1,0.00,'ARROW',NULL,0.00,NULL,0.00,NULL,0.00,'0',NULL,0.0000,NULL,0,NULL,0,'Simple bronze arrows that deal a bit less damage than iron arrows. These are cheap and easily available in huge amounts.','nosound',50,NULL,NULL,NULL,-1,2,"",'Y'); Modified: trunk/src/server/database/mysql/math_scripts.sql =================================================================== --- trunk/src/server/database/mysql/math_scripts.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/math_scripts.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -91,7 +91,7 @@ TargetAVStance = (TargetAttackValue*Target:attack_damage_mod)+(TargetDV*Target:defense_absorb_mod); - FinalDamage = 10*(AVStance-TargetDV); + FinalDamage = AVStance-TargetDV; if(Target:IsNPC) { Attacker:PracticeSkillID(AttackWeapon:Skill1,1); @@ -655,6 +655,3 @@ Result = AverageQuality * log(1+(AvgExtQuality/AverageQuality)); Result = min(Result, 300); " ); - -INSERT INTO math_scripts VALUES( "AttackDefaultDelay", "Result = Latency * 1000;" ); -INSERT INTO math_scripts VALUES( "AttackRangeDelay", "Result = Latency * 1000 + Distance * 100;" ); Modified: trunk/src/server/database/mysql/progress_events.sql =================================================================== --- trunk/src/server/database/mysql/progress_events.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/progress_events.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -71,7 +71,7 @@ INSERT INTO progression_events VALUES("cast Hyper Shot", ' <script> - <hp attacker="Caster" aim="Target" value="-6*Power"/> + <hp attacker="Caster" aim="Target" value="-FinalDamage"/> <msg aim="Caster" text="You hit ${Target} with your Hyper arrow."/> <fx source="Caster" target="Target" type="unattached" name="arrow success"/> @@ -83,12 +83,12 @@ <if t="Target = OrigTarget"> <then> <fx source="Caster" target="Target" name="summon_missile" type="unattached"/> - <hp aim="Target" value="-10*Power"/> + <hp aim="Target" value="-FinalDamage"/> <msg aim="Target" text="${Actor} hits you with a divine arrow!"/> </then> <else> <fx source="OrigTarget" target="Target" name="flame_burst" type="unattached"/> - <hp aim="Target" value="-2*Power"/> + <hp aim="Target" value="-FinalDamage/2"/> <msg aim="Target" text="${Actor}s Divine Arrow Sends waves of energy to damage you"/> </else> </if> @@ -101,12 +101,12 @@ <if t="Target = OrigTarget"> <then> <fx source="Caster" target="Target" name="flame_burst" type="unattached"/> - <hp aim="Target" value="-Power/2"/> + <hp aim="Target" value="-FinalDamage/2"/> <msg aim="Target" text="${Actor} Pounds you with hammer smash!"/> </then> <else> <fx source="Caster" target="Target" name="flame_burst" type="unattached"/> - <hp aim="Target" value="-Power/3"/> + <hp aim="Target" value="-FinalDamage/3"/> <msg aim="Target" text="${Actor} hammer smash hits you, flames sprout from your body!"/> </else> </if> Modified: trunk/src/server/database/mysql/server_options.sql =================================================================== --- trunk/src/server/database/mysql/server_options.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/server_options.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -29,7 +29,7 @@ # Dumping data for table server_options # -INSERT INTO `server_options` VALUES ('db_version','1277'); +INSERT INTO `server_options` VALUES ('db_version','1278'); INSERT INTO `server_options` VALUES ('game_time','15:00'); INSERT INTO `server_options` VALUES ('game_date','100-1-1'); INSERT INTO `server_options` VALUES ('instruments_category','27'); Modified: trunk/src/server/database/mysql/upgrade_schema.sql =================================================================== --- trunk/src/server/database/mysql/upgrade_schema.sql 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/database/mysql/upgrade_schema.sql 2014-04-18 22:45:28 UTC (rev 9456) @@ -1848,7 +1848,15 @@ ADD `flags` varchar(200) NOT NULL DEFAULT '' COMMENT 'The flags to apply to the item.' AFTER `lock_skill`; UPDATE `server_options` SET `option_value`='1277' WHERE `option_name`='db_version'; +# +# Changed attacks table. +# +DROP table attacks; +DROP table attack_types; +SOURCE attacks.sql; +SOURCE attack_types.sql; +UPDATE `server_options` SET `option_value`='1278' WHERE `option_name`='db_version'; # Insert your upgrade before this line. Remember when you set a new db_version # to update the server_options.sql file and update psserver.cpp as well. Modified: trunk/src/server/psserver.cpp =================================================================== --- trunk/src/server/psserver.cpp 2014-04-18 19:31:29 UTC (rev 9455) +++ trunk/src/server/psserver.cpp 2014-04-18 22:45:28 UTC (rev 9456) @@ -94,7 +94,7 @@ #include "workmanager.h" // Remember to bump this in server_options.sql and add to upgrade_schema.sql! -#define DATABASE_VERSION_STR "1277" +#define DATABASE_VERSION_STR "1278" psCharacterLoader psServer::CharacterLoader; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |