Skip to content

Commit

Permalink
Generic schemes docs / updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloreck committed Aug 20, 2023
1 parent 221cf74 commit e8a6767
Show file tree
Hide file tree
Showing 64 changed files with 442 additions and 422 deletions.
10 changes: 10 additions & 0 deletions src/engine/core/objects/animation/state_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ export enum EStateActionId {
SMARTCOVER_EXIT = 81,
}

/**
* todo;
*/
export enum ESmartCoverState {
FIRE_TARGET = "fire_target",
FIRE_NO_LOOKOUT_TARGET = "fire_no_lookout_target",
IDLE_TARGET = "idle_target",
LOOKOUT_TARGET = "lookout_target",
}

/**
* todo;
*/
Expand Down
85 changes: 80 additions & 5 deletions src/engine/core/objects/binders/creature/StalkerBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ import { PostCombatIdle } from "@/engine/core/schemes/combat_idle/PostCombatIdle
import { SchemeHear } from "@/engine/core/schemes/hear/SchemeHear";
import { activateMeetWithObject, updateObjectInteractionAvailability } from "@/engine/core/schemes/meet/utils";
import { SchemeReachTask } from "@/engine/core/schemes/reach_task/SchemeReachTask";
import { SchemeLight } from "@/engine/core/schemes/sr_light/SchemeLight";
import { ISchemeWoundedState } from "@/engine/core/schemes/wounded";
import { pickSectionFromCondList, readIniString, TConditionList } from "@/engine/core/utils/ini";
import { IObjectJobDescriptor } from "@/engine/core/utils/job";
import { LuaLogger } from "@/engine/core/utils/logging";
import { getObjectCommunity, getObjectSquad } from "@/engine/core/utils/object";
import { getObjectCommunity, getObjectSquad, isUndergroundLevel } from "@/engine/core/utils/object";
import { ERelation, setClientObjectRelation, setObjectSympathy } from "@/engine/core/utils/relation";
import {
emitSchemeEvent,
Expand All @@ -64,6 +63,7 @@ import {
import { createEmptyVector } from "@/engine/core/utils/vector";
import { communities, TCommunity } from "@/engine/lib/constants/communities";
import { ACTOR_ID } from "@/engine/lib/constants/ids";
import { misc } from "@/engine/lib/constants/items/misc";
import { MAX_U16 } from "@/engine/lib/constants/memory";
import {
ActionPlanner,
Expand Down Expand Up @@ -93,7 +93,8 @@ import { ESchemeType } from "@/engine/lib/types/scheme";
const logger: LuaLogger = new LuaLogger($filename);

/**
* todo;
* Binder for client side objects representing stalkers.
* Wraps logics and adds additional layers when stalker objects are online.
*/
@LuabindClass()
export class StalkerBinder extends object_binder {
Expand Down Expand Up @@ -279,7 +280,7 @@ export class StalkerBinder extends object_binder {
}

if (time_global() - this.lastUpdatedAt > 1000) {
SchemeLight.checkObjectLight(object);
this.updateLightState(object);
this.lastUpdatedAt = time_global();
}

Expand Down Expand Up @@ -315,6 +316,80 @@ export class StalkerBinder extends object_binder {
}
}

/**
* todo: Description.
*/
public updateLightState(object: ClientObject): void {
if (object === null) {
return;
}

const torch: Optional<ClientObject> = object.object(misc.device_torch);
const isCurrentlyIndoor: boolean = isUndergroundLevel(level.name());

if (torch === null) {
return;
}

let light: boolean = false;
let forced: boolean = false;

/*
if (benchmark.light) {
light = true;
forced = true;
}
*/

if (!object.alive()) {
light = false;
forced = true;
}

if (!forced) {
for (const [, manager] of registry.lightZones) {
[light, forced] = manager.checkStalker(object);

if (forced === true) {
break;
}
}
}

if (!forced) {
const htime = level.get_time_hours();

if (htime <= 4 || htime >= 22) {
light = true;
}

if (light === false) {
if (isCurrentlyIndoor) {
light = true;
}
}
}

if (!forced && light === true) {
const scheme = registry.objects.get(object.id()).activeScheme!;

if (scheme === EScheme.CAMPER || scheme === EScheme.SLEEPER) {
light = false;
forced = true;
}
}

if (!forced && light) {
if (object.best_enemy() !== null && !isCurrentlyIndoor) {
light = false;
}
}

if (light !== null) {
torch.enable_attachable_item(light);
}
}

public override net_save_relevant(): boolean {
return true;
}
Expand Down Expand Up @@ -432,7 +507,7 @@ export class StalkerBinder extends object_binder {
emitSchemeEvent(this.object, this.state[this.state.activeScheme!]!, ESchemeEvent.DEATH, victim, who);
}

SchemeLight.checkObjectLight(this.object);
this.updateLightState(this.object);
DropManager.getInstance().createCorpseReleaseItems(this.object);

unregisterHelicopterEnemy(this.helicopterEnemyIndex!);
Expand Down
14 changes: 7 additions & 7 deletions src/engine/core/objects/state/StalkerMoveManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,14 @@ export class StalkerMoveManager {
public reset(
walkPath: TName,
walkPathInfo: LuaArray<IWaypointData>,
lookPath: Optional<string>,
lookPathInfo: Optional<LuaArray<IWaypointData>>,
team: Optional<string>,
lookPath: Optional<string> = null,
lookPathInfo: Optional<LuaArray<IWaypointData>> = null,
team: Optional<string> = null,
suggestedState: Optional<any>,
moveCbInfo: Optional<{ obj: AnyObject; func: AnyCallable }>,
noValidation: Optional<boolean>,
fplaceholder: Optional<any>,
useDefaultSound: Optional<boolean>
moveCbInfo: Optional<{ obj: AnyObject; func: AnyCallable }> = null,
noValidation: Optional<boolean> = null,
fplaceholder: Optional<any> = null,
useDefaultSound: Optional<boolean> = null
): void {
this.ptWaitTime = DEFAULT_WAIT_TIME;
this.suggestedState = suggestedState;
Expand Down
9 changes: 7 additions & 2 deletions src/engine/core/schemes/base/AbstractScheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export abstract class AbstractScheme {
}

/**
* Add scheme state to client object.
* Add scheme state handlers to client object states.
* Usually used to add actions, evaluators or custom managers.
*
* @param object - target client object
* @param ini - ini file describing object logic
Expand Down Expand Up @@ -119,7 +120,11 @@ export abstract class AbstractScheme {
}

/**
* todo: Description.
* Ub-subscribe provided action class from scheme events.
*
* @param object - target client object owning scheme states
* @param state - scheme state owning action subscriber
* @param action - action subscribing handler
*/
public static unsubscribe(object: ClientObject, state: IBaseSchemeState, action: AnyObject): void {
if (state.actions) {
Expand Down
19 changes: 18 additions & 1 deletion src/engine/core/schemes/base/AbstractSchemeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ export abstract class AbstractSchemeManager<T extends IBaseSchemeState> implemen
logger.info("Net destroy:", this.state?.scheme, this.object.name());
}

/**
* Handle scheme hit callback.
* Emits when objects are hit by something.
*
* @param object - target client object being hit
* @param amount - amount of hit applied
* @param direction - direction of hit
* @param who - client object which is source of hit
* @param boneIndex - index of bone being hit
*/
public onHit(
object: ClientObject,
amount: TCount,
Expand All @@ -54,7 +64,14 @@ export abstract class AbstractSchemeManager<T extends IBaseSchemeState> implemen
logger.info("Waypoint:", this.state?.scheme, this.object.name());
}

public onDeath(victim: ClientObject, who: Optional<ClientObject>): void {
/**
* Handle scheme death callback.
* Emits when objects are dying.
*
* @param object - target client object dying
* @param who - client object who killed the object
*/
public onDeath(object: ClientObject, who: Optional<ClientObject>): void {
logger.info("Death:", this.state?.scheme, this.object.name());
}

Expand Down
2 changes: 2 additions & 0 deletions src/engine/core/schemes/base/id/evaluator_ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export enum EEvaluatorId {
IS_STATE_IDLE_ALIFE = BASE + 102, // 176
IS_STATE_LOGIC_ACTIVE = BASE + 104, // 178
IS_STATE_IDLE_ITEMS = BASE + 105, // 179
// Check if smart cover scheme is active and should go in cover.
IS_SMART_COVER_NEEDED = BASE + 401, // 475
// Check if combat smart cover is needed and should go in cover for fighting cover.
CAN_USE_SMART_COVER_IN_COMBAT = BASE + 402, // 476
IS_ANIMPOINT_NEEDED = BASE + 501, // 575
IS_ANIMPOINT_REACHED = BASE + 502, // 576
Expand Down
2 changes: 1 addition & 1 deletion src/engine/core/schemes/ph_hit/ISchemePhysicalHitState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IBaseSchemeState } from "@/engine/core/schemes/base";
import { TRate } from "@/engine/lib/types";

/**
* todo;
* State describing physical hit scheme.
*/
export interface ISchemePhysicalHitState extends IBaseSchemeState {
power: TRate;
Expand Down
27 changes: 11 additions & 16 deletions src/engine/core/schemes/ph_hit/PhysicalHitManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,22 @@ import { Hit, Vector } from "@/engine/lib/types";
* todo;
*/
export class PhysicalHitManager extends AbstractSchemeManager<ISchemePhysicalHitState> {
/**
* todo: Description.
*/
public override resetScheme(): void {
const p1: Vector = new patrol(this.state.dir_path).point(0);
const p2: Vector = this.object.position();
const patrolPoint: Vector = new patrol(this.state.dir_path).point(0);
const objectPosition: Vector = this.object.position();

const objectHit: Hit = new hit();

const hitObject: Hit = new hit();
objectHit.power = this.state.power;
objectHit.impulse = this.state.impulse;
objectHit.bone(this.state.bone);
objectHit.type = hit.strike;
objectHit.direction = copyVector(patrolPoint).sub(objectPosition); // todo: is copy needed?
objectHit.draftsman = this.object;

hitObject.power = this.state.power;
hitObject.impulse = this.state.impulse;
hitObject.bone(this.state.bone);
hitObject.type = hit.strike;
hitObject.direction = copyVector(p1).sub(p2); // subVectors util?
hitObject.draftsman = this.object;
this.object.hit(hitObject);
this.object.hit(objectHit);
}

/**
* todo: Description.
*/
public update(): void {
trySwitchToAnotherSection(this.object, this.state);
}
Expand Down
16 changes: 10 additions & 6 deletions src/engine/core/schemes/ph_idle/ISchemePhysicalIdleState.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { IBaseSchemeLogic, IBaseSchemeState } from "@/engine/core/schemes/base";
import type { IBoneStateDescriptor } from "@/engine/core/utils/ini/ini_types";
import type { LuaArray, Optional } from "@/engine/lib/types";
import type { LuaArray, Optional, TLabel } from "@/engine/lib/types";

/**
* todo;
* Descriptor to describe idle state scheme.
*/
export interface ISchemePhysicalIdleState extends IBaseSchemeState {
hit_on_bone: LuaArray<IBoneStateDescriptor>;
nonscript_usable: boolean;
on_use: Optional<IBaseSchemeLogic>;
tips: string;
// List of condists for each bone index hit handling.
bonesHitCondlists: LuaArray<IBoneStateDescriptor>;
// Whether object should be set as nonscript usable.
isNonscriptUsable: boolean;
// Logics to apply when object is used.
onUse: Optional<IBaseSchemeLogic>;
// Tip to disable when hover over object.
tip: TLabel;
}
32 changes: 13 additions & 19 deletions src/engine/core/schemes/ph_idle/PhysicalIdleManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { ClientObject, Optional, TCount, TIndex, TSection, Vector } from "@/engi
const logger: LuaLogger = new LuaLogger($filename);

/**
* todo;
* Manager to handle idle state of physical objects.
*/
export class PhysicalIdleManager extends AbstractSchemeManager<ISchemePhysicalIdleState> {
public override resetScheme(): void {
this.object.set_nonscript_usable(this.state.nonscript_usable);
this.object.set_nonscript_usable(this.state.isNonscriptUsable);
}

public update(): void {
Expand All @@ -32,34 +32,28 @@ export class PhysicalIdleManager extends AbstractSchemeManager<ISchemePhysicalId
who: Optional<ClientObject>,
boneIndex: TIndex
): void {
logger.info("Idle hit:", this.object.name());
logger.info("Idle physical object hit:", this.object.name());

if (this.state.hit_on_bone.has(boneIndex)) {
if (this.state.bonesHitCondlists.has(boneIndex)) {
const section: TSection = pickSectionFromCondList(
registry.actor,
this.object,
this.state.hit_on_bone.get(boneIndex).state as TConditionList
this.state.bonesHitCondlists.get(boneIndex).state as TConditionList
)!;

switchObjectSchemeToSection(object, this.state.ini, section);
}
}

public override onUse(): Optional<boolean> {
logger.info("Idle use:", this.object.name());
public override onUse(): void {
logger.info("Idle physical object use:", this.object.name());

if (this.state.on_use) {
if (
switchObjectSchemeToSection(
this.object,
this.state.ini!,
pickSectionFromCondList(registry.actor, this.object, this.state.on_use.condlist)!
)
) {
return true;
}
if (this.state.onUse) {
switchObjectSchemeToSection(
this.object,
this.state.ini,
pickSectionFromCondList(registry.actor, this.object, this.state.onUse.condlist)
);
}

return null;
}
}
6 changes: 5 additions & 1 deletion src/engine/core/schemes/ph_idle/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
## scheme
## ph_idle

description

## ini parameters

```
hit_on_bone - ?
nonscript_usable - ?
on_use - ?
tips - ?
```
Loading

0 comments on commit e8a6767

Please sign in to comment.