1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-01 16:37:45 +00:00

First batch of 5.58 updates:

- Common defs, ActorControls and packet updates (more to come later).
  - Haste added to chara base stats for later use.
  - Acquiring HQ items support (HQ status not yet saved to db, need table modification).
  - Event item support.
  - Load more default zones.
  - Quest related debug commands.
This commit is contained in:
collett 2023-02-05 19:37:17 +09:00
parent c82be40934
commit 14860047b6
22 changed files with 373 additions and 44 deletions

View file

@ -78,6 +78,60 @@ namespace Sapphire::Common
Enemy = 4,
};
enum ActorKind : int32_t
{
ACTOR_KIND_PC = 0x0,
ACTOR_KIND_NPC = 0x1,
ACTOR_KIND_RETAINER = 0x2,
ACTOR_KIND_BATTLE = 0x3,
ACTOR_KIND_BATTLE_FRIEND = 0x4,
ACTOR_KIND_OBJECT = 0x5,
ACTOR_KIND_TREASURE = 0x6,
ACTOR_KIND_GATHERING = 0x7,
ACTOR_KIND_MAX = 0x8,
};
enum ObjectType : int32_t
{
OBJECT_TYPE_CAMERA = 0x0,
OBJECT_TYPE_CAMERA_MAYA = 0x1,
OBJECT_TYPE_LIGHT = 0x2,
OBJECT_TYPE_PLAYER = 0x3,
OBJECT_TYPE_WEAPON = 0x4,
OBJECT_TYPE_MONSTER = 0x5,
OBJECT_TYPE_TERRAIN = 0x6,
OBJECT_TYPE_BG_OBJECT = 0x7,
OBJECT_TYPE_ENV_LOCATION = 0x8,
OBJECT_TYPE_ENV_SPACE = 0x9,
OBJECT_TYPE_VFX_OBJECT = 0xA,
OBJECT_TYPE_COUNT_MAX = 0xB,
};
enum WarpType : uint8_t
{
WARP_TYPE_NON = 0x0,
WARP_TYPE_NORMAL = 0x1,
WARP_TYPE_NORMAL_POS = 0x2,
WARP_TYPE_EXIT_RANGE = 0x3,
WARP_TYPE_TELEPO = 0x4,
WARP_TYPE_REISE = 0x5,
WARP_TYPE_ = 0x6,
WARP_TYPE_DESION = 0x7,
WARP_TYPE_HOME_POINT = 0x8,
WARP_TYPE_RENTAL_CHOCOBO = 0x9,
WARP_TYPE_CHOCOBO_TAXI = 0xA,
WARP_TYPE_INSTANCE_CONTENT = 0xB,
WARP_TYPE_REJECT = 0xC,
WARP_TYPE_CONTENT_END_RETURN = 0xD,
WARP_TYPE_TOWN_TRANSLATE = 0xE,
WARP_TYPE_GM = 0xF,
WARP_TYPE_LOGIN = 0x10,
WARP_TYPE_LAYER_SET = 0x11,
WARP_TYPE_EMOTE = 0x12,
WARP_TYPE_HOUSING_TELEPO = 0x13,
WARP_TYPE_DEBUG = 0x14,
};
enum ObjKind : uint8_t
{
None = 0x00,
@ -649,6 +703,7 @@ namespace Sapphire::Common
* @param flags Required to be 128, doesn't show combo rings on hotbars otherwise
* @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo
*/
Provoke = 24,
StartActionCombo = 27, // shifted one up from 5.18
ComboSucceed = 28, // shifted one up from 5.18, on retail this is not seen anymore, still working though.
Knockback = 33,
@ -893,6 +948,7 @@ namespace Sapphire::Common
{
Normal = 0x1,
ItemAction = 0x2,
EventItem = 0x3,
MountSkill = 0xD,
};

View file

@ -382,7 +382,7 @@ namespace Sapphire::Network::ActorControl
AllotAttribute = 0x135,
ClearFieldMarkers = 0x13A,
CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable
CameraMode = 0x13B, // param11, 1 = enable, 0 = disable
CharaNameReq = 0x13D, // requests character name by content id
HuntingLogDetails = 0x194,

View file

@ -452,7 +452,7 @@ struct FFXIVIpcEventYieldHandler :
uint32_t eventId;
uint16_t scene;
uint16_t padding;
uint64_t unknown;
uint32_t params[2];
};
struct FFXIVIpcEventYield16Handler :
@ -468,7 +468,7 @@ struct FFXIVIpcCFCommenceHandler :
FFXIVIpcBasePacket< CFCommenceHandler >
{
uint8_t param;
uint8_t dummy[7];
uint8_t padding[7];
};
}

View file

@ -753,8 +753,8 @@ namespace Sapphire::Network::Packets::Server
uint16_t unknown1;
uint16_t unknown2;
uint16_t modelChara;
uint16_t currentMount;
uint16_t rotation;
uint16_t currentMount;
uint16_t activeMinion;
uint8_t spawnIndex;
uint8_t state;
@ -2230,10 +2230,12 @@ namespace Sapphire::Network::Packets::Server
uint8_t classId;
uint8_t u5;
uint8_t level;
uint8_t otherData[368];
uint8_t isLevelSync;
uint8_t unknown[7];
Common::StatusEffect effect[30];
} member[8];
uint64_t someContentId1;
uint64_t someContentId2;
uint64_t partyId;
uint64_t channelId;
uint8_t leaderIndex;
uint8_t partySize;
uint16_t padding1;

View file

@ -123,7 +123,7 @@ private:
{
if( result.param2 == 1 )
{
if( player.giveQuestRewards( getId(), 0 ) )
if( player.giveQuestRewards( getId(), result.param3 ) )
{
player.setQuestUI8BH( getId(), result.param3 );
player.finishQuest( getId() );

View file

@ -0,0 +1,70 @@
#include "EventItemAction.h"
#include <Actor/Player.h>
#include <Network/PacketWrappers/EffectPacket.h>
#include "Manager/PlayerMgr.h"
#include "Manager/EventMgr.h"
#include "Script/ScriptMgr.h"
#include <Service.h>
#include <Network/CommonActorControl.h>
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
#include <Util/UtilMath.h>
#include <Common.h>
using namespace Sapphire;
using namespace Sapphire::Common;
using namespace Sapphire::Network;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;
using namespace Sapphire::World;
using namespace Sapphire::World::Action;
EventItemAction::EventItemAction( Sapphire::Entity::CharaPtr source, uint32_t eventItemId,
Data::EventItemPtr eventItemActionData,
uint32_t sequence, uint64_t targetId ) :
m_eventItemAction( std::move( eventItemActionData ) )
{
m_id = eventItemId;
m_eventItem = eventItemId;
m_pSource = std::move( source );
m_sequence = sequence;
m_targetId = targetId;
m_interruptType = Common::ActionInterruptType::None;
//m_actionKind = Common::SkillType::EventItem;
}
bool EventItemAction::init()
{
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto actionInfoPtr = exdData.get< Data::Action >( m_eventItemAction->action );
m_castTimeMs = static_cast< uint32_t >( m_eventItemAction->castTime * 1000 );
m_recastTimeMs = static_cast< uint32_t >( actionInfoPtr->recast100ms * 100 );
m_cooldownGroup = actionInfoPtr->cooldownGroup;
m_id = m_eventItemAction->action;
return true;
}
void EventItemAction::execute()
{
auto player = getSourceChara()->getAsPlayer();
if( !player )
return;
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
auto& eventMgr = Common::Service< World::Manager::EventMgr >::ref();
player->eventStart( m_targetId, m_eventItemAction->quest, Event::EventHandler::ActionResult, 0, 0 );
scriptMgr.onEventItem( *player, m_eventItem, m_eventItemAction->quest, m_castTimeMs, m_targetId );
player->checkEvent( m_eventItemAction->quest );
}
void EventItemAction::start()
{
m_startTime = Common::Util::getTimeMs();
}

View file

@ -0,0 +1,34 @@
#pragma once
#include "Action.h"
#include <Exd/ExdDataGenerated.h>
namespace Sapphire::Data
{
struct EventItem;
using EventItemPtr = std::shared_ptr< EventItem >;
}
namespace Sapphire::World::Action
{
class EventItemAction : public Action
{
public:
EventItemAction( Entity::CharaPtr source, uint32_t eventItemId, Data::EventItemPtr itemActionData,
uint32_t sequence, uint64_t targetId );
virtual ~EventItemAction() = default;
bool init();
void execute() override;
void start() override;
private:
Data::EventItemPtr m_eventItemAction;
uint32_t m_eventItem;
uint32_t m_sequence;
};
}

View file

@ -732,6 +732,7 @@ void Sapphire::Entity::BNpc::calculateStats()
m_baseStats.pie = static_cast< uint32_t >( base );
m_baseStats.skillSpeed = static_cast< uint32_t >( paramGrowthInfo->baseSpeed );
m_baseStats.spellSpeed = static_cast< uint32_t >( paramGrowthInfo->baseSpeed );
m_baseStats.haste = 100;
m_baseStats.accuracy = static_cast< uint32_t >( paramGrowthInfo->baseSpeed );
m_baseStats.critHitRate = static_cast< uint32_t >( paramGrowthInfo->baseSpeed );
m_baseStats.attackPotMagic = static_cast< uint32_t >( paramGrowthInfo->baseSpeed );

View file

@ -529,8 +529,8 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf
if( nextSlot == -1 )
return;
pEffect->applyStatus();
m_statusEffectMap[ nextSlot ] = pEffect;
pEffect->applyStatus();
auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() );
@ -867,6 +867,12 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base
break;
}
case Common::BaseParam::Haste:
{
value = m_baseStats.haste;
break;
}
case Common::BaseParam::CriticalHit:
{
value = m_baseStats.critHitRate;

View file

@ -48,6 +48,7 @@ namespace Sapphire::Entity
uint32_t healingPotMagic = 0;
uint32_t determination = 0;
uint32_t skillSpeed = 0;
uint32_t haste = 0;
uint32_t resistSlow = 0;
uint32_t resistSilence = 0;

View file

@ -287,6 +287,7 @@ void Sapphire::Entity::Player::calculateStats()
m_baseStats.pie = static_cast< uint32_t >( base );
m_baseStats.skillSpeed = paramGrowthInfo->baseSpeed;
m_baseStats.spellSpeed = paramGrowthInfo->baseSpeed;
m_baseStats.haste = 100;
m_baseStats.accuracy = paramGrowthInfo->baseSpeed;
m_baseStats.critHitRate = paramGrowthInfo->baseSpeed;
m_baseStats.attackPotMagic = paramGrowthInfo->baseSpeed;
@ -339,7 +340,7 @@ void Sapphire::Entity::Player::sendStats()
statPacket->data().healingMagicPotency = getStatValue( Common::BaseParam::HealingMagicPotency );
statPacket->data().skillSpeed = getStatValue( Common::BaseParam::SkillSpeed );
statPacket->data().spellSpeed = getStatValue( Common::BaseParam::SpellSpeed );
statPacket->data().haste = 100;
statPacket->data().haste = getStatValue( Common::BaseParam::Haste );
statPacket->data().criticalHit = getStatValue( Common::BaseParam::CriticalHit );
statPacket->data().defense = getStatValue( Common::BaseParam::Defense );
statPacket->data().magicDefense = getStatValue( Common::BaseParam::MagicDefense );
@ -1183,7 +1184,7 @@ void Sapphire::Entity::Player::update( uint64_t tickCount )
actor->getPos().x, actor->getPos().y, actor->getPos().z ) <= range )
{
if( ( tickCount - m_lastAttack ) > mainWeap->getDelay() )
if( ( tickCount - m_lastAttack ) > ( static_cast< float >( mainWeap->getDelay() ) * ( getStatValue( Common::BaseParam::Haste ) / 100.0f ) ) )
{
m_lastAttack = tickCount;
autoAttack( actor->getAsChara() );

View file

@ -704,7 +704,14 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
{
if( catalogId == 0 )
return nullptr;
if( catalogId > 1000000 )
{
catalogId -= 1000000;
isHq = true;
}
auto item = createTempItem( catalogId, quantity );
if( !item )
return false;
item->setHq( isHq );
return addItem( item, silent, canMerge, sendLootMessage );
}

View file

@ -1091,6 +1091,13 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti
}
}
auto isHq = false;
if( optionalChoice > 1000000 )
{
optionalChoice -= 1000000;
isHq = true;
}
if( optionalItemCount > 0 )
{
for( uint32_t i = 0; i < optionalItemCount; i++ )
@ -1098,7 +1105,7 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti
auto itemId = questInfo->itemReward1.at( i );
if( itemId > 0 && itemId == optionalChoice )
{
addItem( itemId, questInfo->itemCountReward1.at( i ), false, false, true, true );
addItem( itemId, questInfo->itemCountReward1.at( i ), isHq, false, true, true );
break;
}
}

View file

@ -87,6 +87,7 @@ namespace World::Action
TYPE_FORWARD( Action );
TYPE_FORWARD( EventAction );
TYPE_FORWARD( ItemAction );
TYPE_FORWARD( EventItemAction );
TYPE_FORWARD( MountAction );
TYPE_FORWARD( EffectBuilder );
TYPE_FORWARD( EffectResult );

View file

@ -2,6 +2,7 @@
#include "Action/Action.h"
#include "Action/ItemAction.h"
#include "Action/EventItemAction.h"
#include "Action/MountAction.h"
#include "Script/ScriptMgr.h"
#include "Actor/Player.h"
@ -72,6 +73,20 @@ void World::Manager::ActionMgr::handleItemAction( Sapphire::Entity::Player& play
action->start();
}
void World::Manager::ActionMgr::handleEventItemAction( Sapphire::Entity::Player& player, uint32_t itemId, Data::EventItemPtr itemActionData, uint32_t sequence, uint64_t targetId )
{
auto action = Action::make_EventItemAction( player.getAsChara(), itemId, itemActionData, sequence, targetId );
if( !action->init() )
return;
if( itemActionData->castTime )
{
player.setCurrentAction( action );
}
action->start();
}
void World::Manager::ActionMgr::handleMountAction( Entity::Player& player, uint16_t mountId,
Data::ActionPtr actionData, uint64_t targetId,
uint16_t sequence )
@ -94,6 +109,7 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
{
if( !currentAction->preCheck() )
{
player.sendDebug( "preCheck failed" );
// forcefully interrupt the action and reset the cooldown
currentAction->interrupt();
return;

View file

@ -10,6 +10,9 @@ namespace Sapphire::Data
struct ItemAction;
using ItemActionPtr = std::shared_ptr< ItemAction >;
struct EventItem;
using EventItemPtr = std::shared_ptr< EventItem >;
}
namespace Sapphire::World::Manager
@ -28,6 +31,8 @@ namespace Sapphire::World::Manager
void handleItemAction( Entity::Player& player, uint32_t itemId, Data::ItemActionPtr itemActionData,
uint16_t itemSourceSlot, uint16_t itemSourceContainer );
void handleEventItemAction( Entity::Player& player, uint32_t itemId, Data::EventItemPtr itemActionData, uint32_t sequence, uint64_t targetId );
void handleMountAction( Entity::Player& player, uint16_t mountId,
Data::ActionPtr actionData, uint64_t targetId, uint16_t sequence );

View file

@ -16,6 +16,9 @@
#include "DebugCommand/DebugCommand.h"
#include "DebugCommandMgr.h"
#include <datReader/DatCategories/bg/LgbTypes.h>
#include <datReader/DatCategories/bg/lgb.h>
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
@ -33,6 +36,7 @@
#include "Territory/InstanceContent.h"
#include "Territory/QuestBattle.h"
#include "Territory/PublicContent.h"
#include "Territory/InstanceObjectCache.h"
#include "Manager/TerritoryMgr.h"
#include "Event/EventDefs.h"
@ -304,6 +308,76 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player&
{
terriMgr.disableCurrentFestival();
}
else if( subCommand == "QuestVar" )
{
uint16_t questId;
uint8_t index;
uint8_t value;
sscanf( params.c_str(), "%hu %hhu %hhu", &questId, &index, &value );
switch( index )
{
case 1:
{
player.setQuestUI8AH( questId, value );
break;
}
case 2:
{
player.setQuestUI8AL( questId, value );
break;
}
case 3:
{
player.setQuestUI8BH( questId, value );
break;
}
case 4:
{
player.setQuestUI8BL( questId, value );
break;
}
case 5:
{
player.setQuestUI8CH( questId, value );
break;
}
case 6:
{
player.setQuestUI8CL( questId, value );
break;
}
case 7:
{
player.setQuestUI8DH( questId, value );
break;
}
case 8:
{
player.setQuestUI8DL( questId, value );
break;
}
case 9:
{
player.setQuestUI8EH( questId, value );
break;
}
case 10:
{
player.setQuestUI8EL( questId, value );
break;
}
case 11:
{
player.setQuestUI8FH( questId, value );
break;
}
case 12:
{
player.setQuestUI8FL( questId, value );
break;
}
}
}
else if( subCommand == "BitFlag" )
{
uint16_t questId;
@ -604,6 +678,18 @@ void Sapphire::World::Manager::DebugCommandMgr::get( char* data, Entity::Player&
instance->getBranch() );
}
}
else if( ( subCommand == "poprange" ) )
{
uint32_t id, param;
sscanf( params.c_str(), "%u", &id );
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
auto pPopRange = instanceObjectCache.getPopRange( player.getCurrentTerritory()->getTerritoryTypeId(), id );
if( pPopRange )
{
player.sendNotice( "x:{}, y:{}, z:{}", pPopRange->header.transform.translation.x, pPopRange->header.transform.translation.y, pPopRange->header.transform.translation.z );
}
}
else
{
player.sendUrgent( "{0} is not a valid GET command.", subCommand );

View file

@ -112,7 +112,13 @@ bool Sapphire::World::Manager::TerritoryMgr::isInstanceContentTerritory( uint32_
intendedUse == TerritoryIntendedUse::RaidFights ||
intendedUse == TerritoryIntendedUse::Raids ||
intendedUse == TerritoryIntendedUse::TreasureMapInstance ||
intendedUse == TerritoryIntendedUse::EventTrial;
intendedUse == TerritoryIntendedUse::EventTrial ||
intendedUse == TerritoryIntendedUse::DiademV1 ||
intendedUse == TerritoryIntendedUse::DiademV2 ||
intendedUse == TerritoryIntendedUse::DiademV3 ||
intendedUse == TerritoryIntendedUse::Eureka ||
intendedUse == TerritoryIntendedUse::Bozja ||
intendedUse == TerritoryIntendedUse::Wedding;
}
bool Sapphire::World::Manager::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const
@ -148,8 +154,11 @@ bool Sapphire::World::Manager::TerritoryMgr::isDefaultTerritory( uint32_t territ
return pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Town ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorld ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea;
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::GoldSaucer ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::ChocoboSquare ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::BeforeTrialDung;
}
bool Sapphire::World::Manager::TerritoryMgr::isHousingTerritory( uint32_t territoryTypeId ) const
@ -327,8 +336,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createQuestBattle
if( !pQuestInfo )
return nullptr;
if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
return nullptr;
//if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
// return nullptr;
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );
@ -361,8 +370,8 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon
if( !pInstanceContent )
return nullptr;
if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
return nullptr;
//if( !isInstanceContentTerritory( pContentFinderCondition->territoryType ) )
// return nullptr;
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );

View file

@ -48,8 +48,10 @@ namespace Sapphire::World::Manager
MSQPrivateArea = 15,
Raids = 16,
RaidFights = 17,
ChocoboSquare = 19,
ChocoboTutorial = 21,
Wedding = 22,
GoldSaucer = 23,
DiademV1 = 26,
BeginnerTutorial = 27,
PvPTheFeast = 28,

View file

@ -67,6 +67,14 @@ void Sapphire::Network::GameConnection::actionHandler( const Packets::FFXIVARR_P
break;
}
case Common::SkillType::EventItem:
{
auto action = exdData.get< Data::EventItem >( actionId );
assert( action );
actionMgr.handleEventItemAction( player, actionId, action, sequence, targetId );
break;
}
case Common::SkillType::MountSkill:
{
auto action = exdData.get< Data::Action >( 4 );

View file

@ -109,7 +109,9 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
else
player.setAutoattack( false );
player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) );
// the client seems to ignore source actor of this packet and always set auto-attack on itself. causing everyone on screen take their weapons out
player.queuePacket( makeActorControl( player.getId(), 1, param11, 1 ) );
//player.sendToInRangeSet( makeActorControl( player.getId(), 1, param11, 1 ) );
break;
}
@ -523,6 +525,18 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
}
break;
}
case ClientTriggerType::CameraMode:
{
if( param11 == 1 )
{
player.setOnlineStatusMask( player.getOnlineStatusMask() | 0x0000000000040000 );
}
else
{
player.setOnlineStatusMask( player.getOnlineStatusMask() & 0xFFFFFFFFFFFBFFFF );
}
break;
}
default:
{
Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId );

View file

@ -298,17 +298,20 @@ void Sapphire::Network::GameConnection::eventYieldHandler( const Packets::FFXIVA
auto pParam = reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 + 8 ] );
std::vector< uint32_t > param;
auto paramSize = 0;
switch( opcode )
{
case EventYield2Handler:
paramSize = 2;
break;
case EventYield16Handler:
{
for( int i = 0; i < 16; i++ )
{
param.push_back( pParam[ i ] );
}
paramSize = 16;
break;
}
for( int i = 0; i < paramSize; i++ )
{
param.push_back( pParam[ i ] );
}
std::string eventName = "onEventYield";