Skip to content

Commit

Permalink
Add ApplyActiveDefense and ApplyDamageOnMove Osiris calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Norbyte committed Oct 15, 2019
1 parent 343c6ba commit 95b505e
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 19 deletions.
24 changes: 21 additions & 3 deletions APIDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,26 @@ THEN
NRD_StatusSetReal(_Character, _Handle, "CurrentLifeTime", _NewLifeTime);
```

### Status attributes
### ApplyActiveDefense
`query NRD_ApplyActiveDefense([in](GUIDSTRING)_Character, [in](STRING)_StatusId, [in](REAL)_LifeTime, [out](INTEGER64)_StatusHandle)`

Apply the specified `ACTIVE_DEFENSE` status on the character.
- `_StatusId` - Status to apply
- `_LifeTime` - Lifetime of status in seconds (one turn = 6 seconds)
- `_StatusHandle` - Handle of created status

### ApplyDamageOnMove
`query NRD_ApplyDamageOnMove([in](GUIDSTRING)_Character, [in](STRING)_StatusId, [in](GUIDSTRING)_SourceCharacter, [in](REAL)_LifeTime, [in](REAL)_DistancePerDamage, [out](INTEGER64)_StatusHandle)`

Apply the specified `DAMAGE_ON_MOVE` status on the character.
- `_StatusId` - Status to apply
- `_SourceCharacter` - Character applying the status
- `_LifeTime` - Lifetime of status in seconds (one turn = 6 seconds)
- `_DistancePerDamage` - Distance the character has to pass before damage is triggered (specified in meters)
- `_StatusHandle` - Handle of created status


## Status attributes

| Attribute | Type | Access | Description |
|--|--|--|--|
Expand Down Expand Up @@ -177,7 +196,7 @@ NRD_StatusSetReal(_Character, _Handle, "CurrentLifeTime", _NewLifeTime);

| Attribute | Type | Access | Description |
|--|--|--|--|
| SkillId | String | Read/Write | Skill that was used for the attack |
| SkillId | String | Read/Write | Stats ID of the skill (`SkillData`) that was used for the attack |
| Equipment | Integer | Read/Write | **TODO** *Meaning not known.* |
| DeathType | Enum | Read/Write | A value from the `Death Type` enumeration |
| DamageType | Enum | Read/Write | A value from the `Damage Type` enumeration |
Expand Down Expand Up @@ -229,7 +248,6 @@ In addition to the parameters listed in [StatusHit attributes](#statushit-attrib
|--|--|--|
| CallCharacterHit | Flag | **TODO this is complex!** |
| HitType | Integer | **TODO** *Used in many places, meaning not known. Possibly a bitmask. Values 0, 1, 2, 4 and 5 have special significance* |
| RollForDamage | Integer | Determines if the hit is guaranteed. 0 = An RNG roll determines whether the attack hits or is dodged/missed/blocked; the appropriate flag (`Hit`, `Dodged`, `Missed`, `Blocked`) is set automatically. 1 = No RNG roll is performed and the attack always hits; flag `Hit` is set automatically. |
| RollForDamage | Integer | Determines whether the hit is guaranteed. 0 = An RNG roll determines whether the attack hits or is dodged/missed/blocked; the appropriate flag (`Hit`, `Dodged`, `Missed`, `Blocked`) is set automatically. 1 = No RNG roll is performed and the attack always hits; flag `Hit` is set automatically. |
| CriticalRoll | Integer | Determines the outcome of the critical hit roll. 0 = An RNG roll determines whether the attack is a critical hit; flag `CriticalHit` is set depending on the result. 1 = The hit is always a critical hit; flag `CriticalHit` is set automatically. 2 = The hit is not a critical hit. |
| ProcWindWalker | Flag | |
Expand Down
102 changes: 86 additions & 16 deletions OsiInterface/DivInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ namespace osidbg
struct CRPGStats_Object
{
void * VMT;
uint32_t A;
uint32_t Unused1;
uint32_t Handle;
uint32_t Level;
uint32_t ModifierListIndex;
uint32_t Unused2;
int32_t * IndexedProperties;
Expand Down Expand Up @@ -542,24 +542,24 @@ namespace osidbg
uint32_t NetID;
uint32_t _Pad0;
uint64_t U1;
FixedString StatusId;
uint32_t CanEnterChance;
float StartTimer;
float LifeTime;
float CurrentLifeTime;
float TurnTimer;
float Strength;
float StatsMultiplier;
CauseType DamageSourceType;
FixedString StatusId; // Saved
uint32_t CanEnterChance; // Saved
float StartTimer; // Saved
float LifeTime; // Saved
float CurrentLifeTime; // Saved
float TurnTimer; // Saved
float Strength; // Saved
float StatsMultiplier; // Saved
CauseType DamageSourceType; // Saved
uint8_t _Pad1[3];
ObjectHandle StatusHandle;
ObjectHandle TargetCIHandle;
ObjectSet<ObjectHandle> StatusOwner;
ObjectHandle StatusSourceHandle;
ObjectSet<ObjectHandle> StatusOwner; // Saved
ObjectHandle StatusSourceHandle; // Saved
ObjectHandle SomeHandle;
uint8_t Flags2;
uint8_t Flags0;
uint8_t Flags1;
uint8_t Flags2; // Saved
uint8_t Flags0; // Saved
uint8_t Flags1; // Saved
uint8_t _Pad2;
uint32_t _Pad3;
};
Expand Down Expand Up @@ -645,6 +645,76 @@ namespace osidbg
uint32_t Unkn3;
};

struct EsvStatusConsume : public EsvStatus
{
ObjectSet<FixedString> Skill; // Saved
ObjectSet<FixedString> Items; // Saved
PrimitiveSet<uint32_t> ResetCooldownsSet; // Set<TSkillAbility>
int64_t field_E0;
int64_t field_E8;
bool ResetAllCooldowns; // Saved
bool ResetOncePerCombat; // Saved
bool ScaleWithVitality; // Saved
bool LoseControl; // Saved
FixedString ApplyStatusOnTick;
ObjectSet<ObjectHandle> ItemHandles; // Saved
float EffectTime; // Saved
FixedString StatsId; // Saved
ObjectSet<void *> StatsIDs; // Set<StatsData>
FixedString StackId;
FixedString OriginalWeaponStatsId;
FixedString OverrideWeaponStatsId;
ObjectHandle OverrideWeaponHandle;
int field_170;
int SavingThrow;
Vector3 SourceDirection; // Saved
uint8_t _Pad10[4];
PrimitiveSet<void *> SurfaceChangeSet; // Set<SurfaceChange>
int field_198;
int field_19C;
int64_t field_1A0;
int Turn; // Saved
int field_1AC;
EsvStatus * AuraStatus; // Saved
int HealEffectOverride; // Saved
char field_1BC;
char field_1BD;
char field_1BE;
char field_1BF;
};

struct EsvStatusDamage : public EsvStatusConsume
{
int32_t DamageEvent; // Saved
float HitTimer; // Saved
float TimeElapsed; // Saved
int DamageLevel; // Saved
uint64_t DamageStats; // Saved
bool SpawnBlood; // Saved
uint8_t _Pad20[7];
};


struct EsvStatusDamageOnMove : public EsvStatusDamage
{
float DistancePerDamage; // Saved
float DistanceTraveled; // Saved
FixedString _Unknown;
};

struct EsvStatusActiveDefense : public EsvStatusConsume
{
int Charges;
Vector3 TargetPos;
ObjectHandle TargetHandle;
int _Unkn10;
FixedString FixedStr;
uint64_t _Unkn1011;
ObjectSet<void *> Targets; // ObjectSet<StatusActiveDefenseTargetData>
ObjectSet<ObjectHandle> PreviousTargets;
};


struct EsvStatusManager
{
uint64_t U1[8];
Expand Down
152 changes: 152 additions & 0 deletions OsiInterface/Functions/StatusFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,132 @@ namespace osidbg
OsirisPropertyMapSet(gStatusPropertyMap, status, args, 2, Type);
}
}

template <class T>
T * ConstructStatus(EsvStatusManager * statusMachine, char const * statusId, StatusType type)
{
auto statusIdFs = ToFixedString(statusId);
T * status{ nullptr };

if (statusIdFs) {
status = (T *)gOsirisProxy->GetLibraryManager().StatusMachineCreateStatus(statusMachine, statusIdFs, 0);
}

if (status == nullptr) {
OsiError("Status does not exist: " << statusId);
return nullptr;
}

if (status->GetStatusId() != type) {
// TODO - dangling status ptr!
OsiError("Status has incorrect type: " << statusId);
return nullptr;
}

return status;
}


bool ApplyActiveDefense(OsiArgumentDesc & args)
{
auto characterGuid = args.Get(0).String;
auto statusId = args.Get(1).String;
auto lifeTime = args.Get(2).Float;

auto character = FindCharacterByNameGuid(characterGuid);
if (character == nullptr) {
OsiError("Character " << characterGuid << " does not exist!");
return false;
}

auto statusMachine = character->StatusManager;
if (!statusMachine) {
OsiError("Character has no StatusMachine!");
return false;
}

auto status = ConstructStatus<EsvStatusActiveDefense>(statusMachine, statusId, StatusType::ActiveDefense);
if (status == nullptr) {
return false;
}

if (lifeTime < 0.0f) {
status->Flags0 |= SF0_KeepAlive;
status->CurrentLifeTime = 1.0f;
} else {
status->Flags0 |= SF0_IsLifeTimeSet;
status->LifeTime = lifeTime;
status->CurrentLifeTime = lifeTime;
}

ObjectHandle handle;
character->GetObjectHandle(&handle);

status->TargetHandle = handle;
status->TargetPos = *character->GetTranslate();

gOsirisProxy->GetLibraryManager().StatusMachineApplyStatus(statusMachine, status);
args.Get(3).Int64 = (int64_t)status->StatusHandle;
return true;
}


bool ApplyDamageOnMove(OsiArgumentDesc & args)
{
auto characterGuid = args.Get(0).String;
auto statusId = args.Get(1).String;
auto sourceCharacterGuid = args.Get(2).String;
auto lifeTime = args.Get(3).Float;
auto distancePerDamage = args.Get(4).Float;

auto character = FindCharacterByNameGuid(characterGuid);
if (character == nullptr) {
OsiError("Character " << characterGuid << " does not exist!");
return false;
}

auto statusMachine = character->StatusManager;
if (!statusMachine) {
OsiError("Character has no StatusMachine!");
return false;
}

if (distancePerDamage <= 0.01) {
OsiError("DistancePerDamage must be a positive value!");
return false;
}

auto status = ConstructStatus<EsvStatusDamageOnMove>(statusMachine, statusId, StatusType::DamageOnMove);
if (status == nullptr) {
return false;
}

if (lifeTime < 0.0f) {
status->Flags0 |= SF0_KeepAlive;
status->CurrentLifeTime = 1.0f;
} else {
status->Flags0 |= SF0_IsLifeTimeSet;
status->LifeTime = lifeTime;
status->CurrentLifeTime = lifeTime;
}

auto sourceCharacter = FindCharacterByNameGuid(sourceCharacterGuid);
if (sourceCharacter == nullptr) {
status->StatusSourceHandle = ObjectHandle{};
} else {
ObjectHandle sourceHandle;
sourceCharacter->GetObjectHandle(&sourceHandle);
status->StatusSourceHandle = sourceHandle;
}

status->StartTimer = 0.0f;
status->StatsMultiplier = 1.0f;
status->DistancePerDamage = distancePerDamage;

gOsirisProxy->GetLibraryManager().StatusMachineApplyStatus(statusMachine, status);
args.Get(5).Int64 = (int64_t)status->StatusHandle;
return true;
}
}

void CustomFunctionLibrary::RegisterStatusFunctions()
Expand Down Expand Up @@ -287,6 +413,32 @@ namespace osidbg
}
);
StatusIteratorEventHandle = functionMgr.Register(std::move(statusIteratorEvent));

auto applyActiveDefense = std::make_unique<CustomQuery>(
"NRD_ApplyActiveDefense",
std::vector<CustomFunctionParam>{
{ "Character", ValueType::GuidString, FunctionArgumentDirection::In },
{ "StatusId", ValueType::String, FunctionArgumentDirection::In },
{ "LifeTime", ValueType::Real, FunctionArgumentDirection::In },
{ "StatusHandle", ValueType::Integer64, FunctionArgumentDirection::Out },
},
&func::ApplyActiveDefense
);
functionMgr.Register(std::move(applyActiveDefense));

auto applyDamageOnMove = std::make_unique<CustomQuery>(
"NRD_ApplyDamageOnMove",
std::vector<CustomFunctionParam>{
{ "Character", ValueType::GuidString, FunctionArgumentDirection::In },
{ "StatusId", ValueType::String, FunctionArgumentDirection::In },
{ "SourceCharacter", ValueType::GuidString, FunctionArgumentDirection::In },
{ "LifeTime", ValueType::Real, FunctionArgumentDirection::In },
{ "DistancePerDamage", ValueType::Real, FunctionArgumentDirection::In },
{ "StatusHandle", ValueType::Integer64, FunctionArgumentDirection::Out },
},
&func::ApplyDamageOnMove
);
functionMgr.Register(std::move(applyDamageOnMove));
}

}

0 comments on commit 95b505e

Please sign in to comment.