Changes related to ray-collision, and luprex global variable stuff

This commit is contained in:
2025-01-14 18:37:31 -05:00
parent cd3e78a206
commit a01f6f4e7b
24 changed files with 180 additions and 317 deletions

View File

@@ -24,3 +24,60 @@ ManualIPAddress=
[/Script/Engine.UserInterfaceSettings] [/Script/Engine.UserInterfaceSettings]
UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000)),DefaultValue=340282346638528859811704183484516925440.000000,PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant),ExternalCurve=None) UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000)),DefaultValue=340282346638528859811704183484516925440.000000,PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant),ExternalCurve=None)
[/Script/Engine.CollisionProfile]
-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False)
-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
-Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False)
-Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False)
-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False)
-Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False)
-Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False)
-Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False)
-Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False)
-Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
+Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision")
+Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.")
+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ")
+Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ")
+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors")
+Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors")
+Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.")
+Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.")
+Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.")
+Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.")
+Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.")
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Clickable")
-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")
-ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor")
-ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic")
+ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
+ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
+ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")
+ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor")
+ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic")
-CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic")
-CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic")
-CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle")
-CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")
+CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic")
+CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic")
+CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle")
+CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")

Binary file not shown.

Binary file not shown.

View File

@@ -87,8 +87,8 @@ void AIntegrationGameModeBase::ResetToInitialState()
PlayerId = 0; PlayerId = 0;
// Clear the look-at state; // Clear the look-at state;
PreviousLookAt = nullptr; PreviousLookAt.Init();
CurrentLookAt = nullptr; CurrentLookAt.Init();
// Reset the clocks. // Reset the clocks.
EngineSeconds = 0.0; EngineSeconds = 0.0;
@@ -349,8 +349,8 @@ AIntegrationGameModeBase *AIntegrationGameModeBase::GetFromContext(UObject *cont
void AIntegrationGameModeBase::UpdateLookAt() { void AIntegrationGameModeBase::UpdateLookAt() {
// Rotate the variables. // Rotate the variables.
PreviousLookAt = CurrentLookAt; PreviousLookAt = CurrentLookAt;
CurrentLookAt = nullptr; CurrentLookAt.Init();
// Make sure the world is fully configured before we attempt to cast rays. // Make sure the world is fully configured before we attempt to cast rays.
UlxTangible *possessed = TangibleManager->GetPossessedTangible(); UlxTangible *possessed = TangibleManager->GetPossessedTangible();
if (possessed == nullptr) return; if (possessed == nullptr) return;

View File

@@ -47,13 +47,13 @@ public:
int64 GetPlayerId(); int64 GetPlayerId();
UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection")
void SetLookAt(AActor *actor) { CurrentLookAt = actor; } void SetLookAt(const FHitResult &hit) { CurrentLookAt = hit; }
UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection")
AActor *GetLookAt() const { return CurrentLookAt; } const FHitResult &GetLookAt() const { return CurrentLookAt; }
UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection")
bool LookAtChanged() const { return CurrentLookAt != PreviousLookAt; } bool LookAtChanged() const { return CurrentLookAt.HitObjectHandle != PreviousLookAt.HitObjectHandle; }
UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection")
void CalculateLookAt(AActor *Player, APlayerController *PlayerController, APlayerCameraManager *Camera); void CalculateLookAt(AActor *Player, APlayerController *PlayerController, APlayerCameraManager *Camera);
@@ -111,13 +111,13 @@ public:
UPROPERTY() UPROPERTY()
UlxTangibleManager *TangibleManager; UlxTangibleManager *TangibleManager;
// The actor that the player is looking at, previous frame. // The actor that the player was looking at, previous frame.
UPROPERTY() UPROPERTY()
AActor *PreviousLookAt; FHitResult PreviousLookAt;
// The actor that the player is looking at, current frame. // The actor that the player is looking at, current frame.
UPROPERTY() UPROPERTY()
AActor *CurrentLookAt; FHitResult CurrentLookAt;
// The sensitivity level at which a log message triggers a debugger breakpoint. // The sensitivity level at which a log message triggers a debugger breakpoint.
UPROPERTY(EditAnywhere, Category="Debugging Tools") UPROPERTY(EditAnywhere, Category="Debugging Tools")

View File

@@ -77,45 +77,16 @@ UEnhancedInputLocalPlayerSubsystem *UlxUtilityLibrary::GetEnhancedInputLocalPlay
return nullptr; return nullptr;
} }
// bool UlxUtilityLibrary::LineTraceMultipleLines(const AActor* ReferenceActor, const FVector &Offset, bool UlxUtilityLibrary::LineTraceThroughPixel(const APlayerController* PlayerController,
// const TArray<FlxTraceStartTraceEnd> &TraceStartAndTraceEnd, ETraceTypeQuery TraceChannel, FVector2D PixelXY, double MaxDistanceFromCamera,
// bool bTraceComplex, const TArray<AActor*>& ActorsToIgnore, EDrawDebugTrace::Type DrawDebugType, FHitResult& OutHit, bool bIgnoreReferenceActor,
// FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime)
// {
// OutHit.Init();
// OutHit.Distance = FLT_MAX;
// FTransform ReferenceTransform = ReferenceActor->GetActorTransform();
// for (const FlxTraceStartTraceEnd &Points : TraceStartAndTraceEnd) {
// FHitResult OneResult;
// FVector TraceStart = ReferenceTransform.TransformPosition(Points.TraceStart + Offset);
// FVector TraceEnd = ReferenceTransform.TransformPosition(Points.TraceEnd + Offset);
// bool Found = UKismetSystemLibrary::LineTraceSingle(ReferenceActor, TraceStart, TraceEnd, TraceChannel, bTraceComplex,
// ActorsToIgnore, DrawDebugType, OneResult, bIgnoreReferenceActor, TraceColor, TraceHitColor, DrawTime);
// if (Found && (OneResult.Distance < OutHit.Distance))
// {
// OutHit = OneResult;
// }
// }
// if (OutHit.Distance == FLT_MAX) {
// OutHit.Distance = 0.0;
// return false;
// } else {
// return true;
// }
// }
bool UlxUtilityLibrary::LineTraceThroughMousePointer(const APlayerController* PlayerController,
EMouseSpecificationType MouseSpecification, FVector2D ManualMouseXY, double MaxDistanceFromCamera,
ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn, ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn,
const TArray<AActor*>& ActorsToIgnore, AActor *& Actor, FHitResult& HitResult) const TArray<AActor*>& ActorsToIgnore, FHitResult& HitResult)
{ {
const FLinearColor TraceColor = FLinearColor::Red; const FLinearColor TraceColor = FLinearColor::Red;
const FLinearColor TraceHitColor = FLinearColor::Green; const FLinearColor TraceHitColor = FLinearColor::Green;
const double DrawTime = 1.0; const double DrawTime = 1.0;
// Zero out the return values. // Zero out the return values.
Actor = nullptr;
HitResult.Init(); HitResult.Init();
// Sanity check the distance. // Sanity check the distance.
@@ -128,35 +99,9 @@ bool UlxUtilityLibrary::LineTraceThroughMousePointer(const APlayerController* Pl
AActor *PlayerPawn = PlayerController->GetPawn(); AActor *PlayerPawn = PlayerController->GetPawn();
if (!PlayerPawn) return false; if (!PlayerPawn) return false;
// Get the Mouse XY.
FVector2D MouseXY;
switch (MouseSpecification)
{
case EMouseSpecificationType::GetMouseAutomatically:
{
double X, Y;
if (!PlayerController->GetMousePosition(X, Y)) return false;
MouseXY = FVector2D(X, Y);
break;
}
case EMouseSpecificationType::SpecifyMouseInPixels:
{
MouseXY = ManualMouseXY;
break;
}
case EMouseSpecificationType::SpecifyMouseAsZeroToOne:
{
int32 VX, VY;
PlayerController->GetViewportSize(VX, VY);
if ((VX == 0) || (VY == 0)) return false;
MouseXY = ManualMouseXY * FVector2D(VX, VY);
break;
}
}
// Calculate the trace start and trace end positions in world space. // Calculate the trace start and trace end positions in world space.
FVector WorldStart, WorldDirection, WorldEnd; FVector WorldStart, WorldDirection, WorldEnd;
if (!UGameplayStatics::DeprojectScreenToWorld(PlayerController, MouseXY, WorldStart, WorldDirection)) if (!UGameplayStatics::DeprojectScreenToWorld(PlayerController, PixelXY, WorldStart, WorldDirection))
{ {
return false; return false;
} }
@@ -166,12 +111,10 @@ bool UlxUtilityLibrary::LineTraceThroughMousePointer(const APlayerController* Pl
if (UKismetSystemLibrary::LineTraceSingle(PlayerPawn, WorldStart, WorldEnd, TraceChannel, bTraceComplex, if (UKismetSystemLibrary::LineTraceSingle(PlayerPawn, WorldStart, WorldEnd, TraceChannel, bTraceComplex,
ActorsToIgnore, DrawDebugType, HitResult, bIgnorePlayerPawn, TraceColor, TraceHitColor, DrawTime)) ActorsToIgnore, DrawDebugType, HitResult, bIgnorePlayerPawn, TraceColor, TraceHitColor, DrawTime))
{ {
Actor = HitResult.GetActor();
return true; return true;
} }
// Fail. // Fail.
Actor = nullptr;
HitResult.Init(); HitResult.Init();
return false; return false;
} }

View File

@@ -9,31 +9,6 @@
class UEnhancedInputLocalPlayerSubsystem; class UEnhancedInputLocalPlayerSubsystem;
USTRUCT(BlueprintType)
struct INTEGRATION_API FlxTraceStartTraceEnd
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FVector TraceStart;
UPROPERTY(EditAnywhere)
FVector TraceEnd;
};
UENUM(BlueprintType)
enum class EMouseSpecificationType : uint8
{
// Automatically get the mouse position from the player controller. ManualMouseXY should be left blank.
GetMouseAutomatically,
// Specify the mouse position in pixels.
SpecifyMouseInPixels,
// Specify the mouse position as float from zero to one.
SpecifyMouseAsZeroToOne,
};
/** /**
* *
* UlxUtilityLibrary is for functions that are aren't particularly luprex-specific, * UlxUtilityLibrary is for functions that are aren't particularly luprex-specific,
@@ -75,22 +50,18 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Player Controller|Local Player Subsystems") UFUNCTION(BlueprintCallable, BlueprintPure, Category="Player Controller|Local Player Subsystems")
static UEnhancedInputLocalPlayerSubsystem *GetEnhancedInputLocalPlayerSubsystem(AController *Controller); static UEnhancedInputLocalPlayerSubsystem *GetEnhancedInputLocalPlayerSubsystem(AController *Controller);
// // Do a Line Trace by Channel for each start-and-end pair, then return the closest hit result of all. // Do a Line Trace from the camera through a specified pixel.
// UFUNCTION(BlueprintCallable, Category="Collision", meta=(bIgnoreReferenceActor="true", AutoCreateRefTerm="ActorsToIgnore,Offset", DisplayName="Line Trace Multiple Lines by Channel", AdvancedDisplay="TraceColor,TraceHitColor,DrawTime", Keywords="raycast"))
// static bool LineTraceMultipleLines(const AActor* ReferenceActor, const FVector &Offset,
// const TArray<FlxTraceStartTraceEnd> &TraceStartAndTraceEnd, ETraceTypeQuery TraceChannel,
// bool bTraceComplex, const TArray<AActor*>& ActorsToIgnore, EDrawDebugTrace::Type DrawDebugType, FHitResult& OutHit, bool bIgnoreReferenceActor,
// FLinearColor TraceColor = FLinearColor::Red, FLinearColor TraceHitColor = FLinearColor::Green, float DrawTime = 5.0f);
// Do a Line Trace to find the actor that the mouse is pointing at.
// //
// If you have some crosshairs in the viewport, then you can find the // This can be used when you have a crosshair on the screen and you want to
// object under the crosshairs by specifying the crosshairs XY as the // determine the object that the crosshairs are pointing at. It can also
// ManualMouseXY. // be used to do a line trace through the mouse.
//
// Fractional pixels are allowed. Therefore, (0.0, 0.0) is the upper-left corner
// of the upper-left pixel, whereas (0.5, 0.5) is the center of the upper-left pixel.
// //
UFUNCTION(BlueprintCallable, Category="Collision", meta=(AutoCreateRefTerm="ActorsToIgnore", Keywords="raycast")) UFUNCTION(BlueprintCallable, Category="Collision", meta=(AutoCreateRefTerm="ActorsToIgnore", Keywords="raycast"))
static bool LineTraceThroughMousePointer(const APlayerController* PlayerController, static bool LineTraceThroughPixel(const APlayerController* PlayerController,
EMouseSpecificationType MouseSpecification, FVector2D ManualMouseXY, double MaxDistanceFromCamera, FVector2D PixelXY, double MaxDistanceFromCamera,
ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn, ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn,
const TArray<AActor*>& ActorsToIgnore, AActor *& Actor, FHitResult& HitResult); const TArray<AActor*>& ActorsToIgnore, FHitResult& HitResult);
}; };

View File

@@ -1,6 +1,7 @@
#include "world.hpp" #include "world.hpp"
#include "pprint.hpp" #include "pprint.hpp"
#include "serializelua.hpp"
#include <cmath> #include <cmath>
static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) { static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) {
@@ -949,14 +950,7 @@ LuaDefine(global_set, "varname, value",
"|lua identifier." "|lua identifier."
"|" "|"
"|You can store global data using global.set, then you can" "|You can store global data using global.set, then you can"
"|retrieve it using global.get. You can also retrieve data using" "|retrieve it using global.get."
"|gv.varname, which is just shorthand for global.get. You may not"
"|store data using gv.varname=value, this yields the error 'Use "
"|global.set to store data in the global data table.'"
"|"
"|Values stored using global.set are transmitted to all"
"|connected clients immediately. When a new client connects,"
"|he will receive all the global data."
"|" "|"
"|The global data table is not the same thing as the lua " "|The global data table is not the same thing as the lua "
"|environment table. Trying to store data in the lua environment" "|environment table. Trying to store data in the lua environment"
@@ -966,18 +960,16 @@ LuaDefine(global_set, "varname, value",
"|global data table (using global.set) instead of in the lua" "|global data table (using global.set) instead of in the lua"
"|environment table." "|environment table."
"|" "|"
"|There are certain restrictions on the values that you store." "|Data is stored in a serialized form. The data is serialized"
"|Only data that can be serialized according to doc(table.serialize)" "|at the moment you call global.set. It is deserialized when you"
"|can be stored." "|call global.get. Therefore, each time you call global.get, you"
"|construct another copy of the value."
"|" "|"
"|When you store the value, it is immediately serialized and then" "|The serialization routine can only serialize certain kinds of"
"|deserialized again, and the deserialized copy is stored in the" "|values. For example, closures cannot be serialized at all."
"|variable." "|Serializing a tangible serializes the tangible's ID, but"
"|" "|none of the contents of the tangible. See doc(table.serialize)"
// "|When you call global.get, you obtain the copy. Any attempt to" "|for more information about what can and can't be serialized."
// "|mutate the copy will fail with this lua error message: 'Tables"
// "|returned by global.get are immutable.' This rule prevents'"
// "|aliasing between global data and other data structures."
"|") { "|") {
LuaArg varname; LuaArg varname;
LuaArg value; LuaArg value;
@@ -990,8 +982,16 @@ LuaDefine(global_set, "varname, value",
return LS.result(); return LS.result();
} }
// Serialize the data.
StreamBuffer sb;
eng::string error = serialize_lua(LS, value, &sb);
if (!error.empty()) {
luaL_error(L, "%s", error.c_str());
return LS.result();
}
World *w = World::fetch_global_pointer(L); World *w = World::fetch_global_pointer(L);
w->set_global(LS, gvar, value); w->set_global(gvar, sb.view());
return LS.result(); return LS.result();
} }
@@ -1000,16 +1000,33 @@ LuaDefine(global_get, "varname",
"|" "|"
"|See doc(global.set) for information on how to store global data." "|See doc(global.set) for information on how to store global data."
"|" "|"
"|Do not mutate data returned by global.get: doing so will produce" "|Performance note: each time you call global.get, you deserialize the"
"|unpredictable results. Instead, using global.set to mutate global" "|stored serialized version, constructing another copy of the data."
"|variables."
"|") { "|") {
LuaArg varname; LuaArg varname;
LuaRet value; LuaRet value;
LuaVar globaldb; LuaDefStack LS(L, varname, value);
LuaDefStack LS(L, varname, value, globaldb); LS.set(value, LuaNil);
LS.rawget(globaldb, LuaRegistry, "globaldb");
LS.rawget(value, globaldb, varname); // Check the varname argument.
eng::string gvar = LS.ckstring(varname);
if (!sv::is_lua_id(gvar)) {
luaL_error(L, "variable name must be a valid lua identifier: %s", gvar.c_str());
return LS.result();
}
// Fetch the serialized blob.
World *w = World::fetch_global_pointer(L);
std::string_view data = w->get_global(gvar);
if (data.empty()) return LS.result();
// Deserialize the blob.
StreamBuffer sb(data);
eng::string error = deserialize_lua(LS, value, &sb);
if (!error.empty()) {
luaL_error(L, "%s", error.c_str());
return LS.result();
}
return LS.result(); return LS.result();
} }
@@ -1022,8 +1039,8 @@ LuaDefine(global_once, "varname",
"|") { "|") {
LuaArg varname; LuaArg varname;
LuaRet result; LuaRet result;
LuaVar globaldb, flag; LuaDefStack LS(L, varname, result);
LuaDefStack LS(L, varname, flag, result, globaldb); LS.set(result, false);
// Check the varname argument. // Check the varname argument.
eng::string gvar = LS.ckstring(varname); eng::string gvar = LS.ckstring(varname);
@@ -1033,17 +1050,12 @@ LuaDefine(global_once, "varname",
} }
gvar += ":once"; gvar += ":once";
LS.rawget(globaldb, LuaRegistry, "globaldb");
LS.rawget(flag, globaldb, gvar);
if (!LS.isnil(flag)) {
LS.set(result, false);
return LS.result();
}
LS.set(result, true);
World *w = World::fetch_global_pointer(L); World *w = World::fetch_global_pointer(L);
w->set_global(LS, gvar, result); LS.set(result, false);
if (w->get_global(gvar).empty()) {
LS.set(result, true);
w->set_global(gvar, "x");
}
return LS.result(); return LS.result();
} }
@@ -1055,8 +1067,7 @@ LuaDefine(global_clearonce, "varname",
"|uses global.set under the covers." "|uses global.set under the covers."
"|") { "|") {
LuaArg varname; LuaArg varname;
LuaVar null; LuaDefStack LS(L, varname);
LuaDefStack LS(L, varname, null);
// Check the varname argument. // Check the varname argument.
eng::string gvar = LS.ckstring(varname); eng::string gvar = LS.ckstring(varname);
@@ -1066,8 +1077,7 @@ LuaDefine(global_clearonce, "varname",
} }
gvar += ":once"; gvar += ":once";
LS.set(null, LuaNil);
World *w = World::fetch_global_pointer(L); World *w = World::fetch_global_pointer(L);
w->set_global(LS, gvar, null); w->set_global(gvar, "");
return LS.result(); return LS.result();
} }

View File

@@ -5,7 +5,6 @@
#include "traceback.hpp" #include "traceback.hpp"
#include "pprint.hpp" #include "pprint.hpp"
#include "util.hpp" #include "util.hpp"
#include "serializelua.hpp"
#include <iostream> #include <iostream>
@@ -1101,31 +1100,10 @@ std::ostream *World::lthread_print_stream() const {
} }
} }
void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value) { void World::set_global(const eng::string &gvar, std::string_view value) {
lua_State *L = LS0.state();
LuaVar globaldb, copy;
LuaExtStack LS(L, globaldb, copy);
// Serialize then deserialize the data, to produce a copy.
StreamBuffer sb;
eng::string error = serialize_lua(LS, value, &sb);
if (!error.empty()) {
luaL_error(L, "%s", error.c_str());
return;
}
eng::string serialized(sb.view());
error = deserialize_lua(LS, copy, &sb);
if (!error.empty()) {
luaL_error(L, "%s", error.c_str());
return;
}
// Store the copy in the globalDB.
LS.rawget(globaldb, LuaRegistry, "globaldb");
LS.rawset(globaldb, gvar, copy);
// Store the serialized blob. // Store the serialized blob.
gvname_to_serial_[gvar] = serialized; //
gvname_to_serial_[gvar] = value;
// Implement the tracking so that we can rapidly determine which global // Implement the tracking so that we can rapidly determine which global
// variables need to be difference transmitted. // variables need to be difference transmitted.
@@ -1147,6 +1125,15 @@ void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value
} }
} }
const eng::string &World::get_global(const eng::string &gvar) {
static eng::string empty;
auto iter = gvname_to_serial_.find(gvar);
if (iter == gvname_to_serial_.end()) {
return empty;
} else {
return iter->second;
}
}
void World::serialize(StreamBuffer *sb) { void World::serialize(StreamBuffer *sb) {
assert(stack_is_clear()); assert(stack_is_clear());

View File

@@ -305,36 +305,15 @@ void World::diff_source(World *master, StreamBuffer *sb) {
assert(tsb.empty()); assert(tsb.empty());
} }
const eng::string &World::get_gvname_serial(const eng::string &gvar) {
static eng::string empty;
auto iter = gvname_to_serial_.find(gvar);
if (iter == gvname_to_serial_.end()) {
return empty;
} else {
return iter->second;
}
}
void World::patch_globals(StreamBuffer *sb, DebugCollector *dbc) { void World::patch_globals(StreamBuffer *sb, DebugCollector *dbc) {
DebugBlock dbb(dbc, "patch_globals"); DebugBlock dbb(dbc, "patch_globals");
int64_t seqno = sb->read_int64(); int64_t seqno = sb->read_int64();
int32_t total = sb->read_int32(); int32_t total = sb->read_int32();
if (total > 0) { if (total > 0) {
lua_State *L = state();
LuaVar globaldb, copy;
LuaExtStack LS(L, globaldb, copy);
LS.rawget(globaldb, LuaRegistry, "globaldb");
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
eng::string gvar = sb->read_string(); eng::string gvar = sb->read_string();
eng::string serial = sb->read_string(); eng::string serial = sb->read_string();
gvname_to_serial_[gvar] = serial; gvname_to_serial_[gvar] = serial;
StreamBuffer sb(serial);
eng::string error = deserialize_lua(LS, copy, &sb);
if (error.empty()) {
LS.rawset(globaldb, gvar, copy);
} else {
DebugLine(dbc) << "Invalid global serialized data: " << gvar << ":" << error;
}
} }
} }
assign_seqno_ = seqno; assign_seqno_ = seqno;
@@ -350,8 +329,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) {
int64_t count_pos = tsb.total_writes(); int64_t count_pos = tsb.total_writes();
int32_t total_mods = 0; int32_t total_mods = 0;
for (const eng::string &gvar : gvname_modified_) { for (const eng::string &gvar : gvname_modified_) {
const eng::string &mval = master->get_gvname_serial(gvar); const eng::string &mval = master->get_global(gvar);
const eng::string &sval = get_gvname_serial(gvar); const eng::string &sval = get_global(gvar);
if (mval != sval) { if (mval != sval) {
total_mods += 1; total_mods += 1;
tsb.write_string(gvar); tsb.write_string(gvar);
@@ -362,8 +341,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) {
while (iter != master->seqno_to_gvname_.end()) { while (iter != master->seqno_to_gvname_.end()) {
const auto &gvar = iter->second; const auto &gvar = iter->second;
if (gvname_modified_.find(gvar) == gvname_modified_.end()) { if (gvname_modified_.find(gvar) == gvname_modified_.end()) {
const eng::string &mval = master->get_gvname_serial(gvar); const eng::string &mval = master->get_global(gvar);
const eng::string &sval = get_gvname_serial(gvar); const eng::string &sval = get_global(gvar);
if (mval != sval) { if (mval != sval) {
total_mods += 1; total_mods += 1;
tsb.write_string(gvar); tsb.write_string(gvar);

View File

@@ -241,32 +241,6 @@ void World::tangible_set_class(int64_t id, const eng::string &c) const {
LS.rawset(meta, "__index", sclass); LS.rawset(meta, "__index", sclass);
} }
void World::set_global_json(const eng::string &gvar, const eng::string &json) {
LuaVar decoded;
LuaExtStack LS(state(), decoded);
bool ok = json::decode(LS, decoded, json);
if (!ok) {
luaL_error(state(), "invalid json");
return;
}
set_global(LS, gvar, decoded);
}
eng::string World::get_global_json(const eng::string &gvar) {
LuaVar value, globaldb;
LuaExtStack LS(state(), globaldb, value);
LS.rawget(globaldb, LuaRegistry, "globaldb");
LS.rawget(value, globaldb, gvar);
eng::string out;
eng::string error = json::encode(LS, value, out, false, 10000);
if (!error.empty()) {
luaL_error(state(), "%s", error.c_str());
return "";
}
return out;
}
eng::string World::tangible_get_class(int64_t id) const { eng::string World::tangible_get_class(int64_t id) const {
LuaVar tangibles, tan, meta, sclass; LuaVar tangibles, tan, meta, sclass;
LuaExtStack LS(state(), tangibles, tan, meta, sclass); LuaExtStack LS(state(), tangibles, tan, meta, sclass);
@@ -495,24 +469,24 @@ LuaDefine(unittests_world5diffglobals, "", "some unit tests") {
UniqueWorld cs(new World(WORLD_TYPE_PREDICTIVE)); UniqueWorld cs(new World(WORLD_TYPE_PREDICTIVE));
StreamBuffer sb; StreamBuffer sb;
m->set_global_json("x", "3"); m->set_global("x", "3");
ss->diff_globals(m.get(), &sb); ss->diff_globals(m.get(), &sb);
cs->patch_globals(&sb, nullptr); cs->patch_globals(&sb, nullptr);
LuaAssertStrEq(L, cs->get_global_json("x"), "3"); LuaAssertStrEq(L, cs->get_global("x"), "3");
m->set_global_json("x", "4"); m->set_global("x", "4");
m->set_global_json("x", "5"); m->set_global("x", "5");
m->set_global_json("y", "6"); m->set_global("y", "6");
ss->diff_globals(m.get(), &sb); ss->diff_globals(m.get(), &sb);
cs->patch_globals(&sb, nullptr); cs->patch_globals(&sb, nullptr);
LuaAssertStrEq(L, cs->get_global_json("x"), "5"); LuaAssertStrEq(L, cs->get_global("x"), "5");
LuaAssertStrEq(L, cs->get_global_json("y"), "6"); LuaAssertStrEq(L, cs->get_global("y"), "6");
cs->set_global_json("x", "2"); cs->set_global("x", "2");
ss->set_global_json("x", "2"); ss->set_global("x", "2");
ss->diff_globals(m.get(), &sb); ss->diff_globals(m.get(), &sb);
cs->patch_globals(&sb, nullptr); cs->patch_globals(&sb, nullptr);
LuaAssertStrEq(L, cs->get_global_json("x"), "5"); LuaAssertStrEq(L, cs->get_global("x"), "5");
return 0; return 0;
} }

View File

@@ -357,17 +357,18 @@ public:
std::ostream *lthread_print_stream() const; std::ostream *lthread_print_stream() const;
// Set a global variable. // Set a lua global variable.
// //
// This will throw lua errors if there's a problem. // The table just stores strings, and the difference transmitter
// just difference transmits those strings. The strings are meant
// to be serialized lua data structures, but there is no enforcement
// of that here.
// //
void set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value); void set_global(const eng::string &var, std::string_view value);
// Get the serialized value of a global variable. // Get a lua global variable.
// //
// This accessor is used during difference transmission. const eng::string &get_global(const eng::string &var);
//
const eng::string &get_gvname_serial(const eng::string &gvar);
// Allocate a single ID. // Allocate a single ID.
// //
@@ -491,14 +492,6 @@ public:
// //
eng::string tangible_get_class(int64_t id) const; eng::string tangible_get_class(int64_t id) const;
// Store json in a global variable.
//
void set_global_json(const eng::string &gvar, const eng::string &json);
// Get a global variable as json.
//
eng::string get_global_json(const eng::string &gvar);
public: public:
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// //
@@ -671,7 +664,6 @@ private:
std::unique_ptr<eng::ostringstream> lthread_prints_; std::unique_ptr<eng::ostringstream> lthread_prints_;
friend class Tangible; friend class Tangible;
friend void global_set(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value);
friend int lfn_tangible_animate(lua_State *L); friend int lfn_tangible_animate(lua_State *L);
friend int lfn_tangible_build(lua_State *L); friend int lfn_tangible_build(lua_State *L);
friend int lfn_tangible_redirect(lua_State *L); friend int lfn_tangible_redirect(lua_State *L);

View File

@@ -5,6 +5,4 @@
ut-table.lua ut-table.lua
ut-tablecmp.lua ut-tablecmp.lua
basics.lua
uglyglobals.lua
login.lua login.lua

View File

@@ -1,4 +1,5 @@
makeclass('login') makeclass('login')
makeclass("engio")
function login.initialize(actor, place) function login.initialize(actor, place)
dprint("login.initialize:", actor) dprint("login.initialize:", actor)
@@ -6,52 +7,7 @@ function login.initialize(actor, place)
local y = math.random(1, 100) local y = math.random(1, 100)
tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}}) tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}})
end end
function login.interface(actor, place)
gui.menu_item("cb_becomeplayer", "Become a Player")
gui.menu_item("cb_p123", "Print 1, 2, 3")
gui.menu_item("cb_p123_nopredict", "Print 1, 2, 3 nopredict")
gui.menu_item("cb_uglytimedaemon","Start the Time Daemon")
gui.menu_item("cb_seedprng","Seed the PRNG")
end
function login.cb_seedprng(actor,place,dialog)
local result=http.get{method='GET',host='www.random.org',path='/cgi-bin/randbyte',params={nbytes='32',format='f'},verifycertificate=false}
pprint(result)
end -- "GET /cgi-bin/randbyte?nbytes=16384&format=f HTTP/1.0\nHost: www.random.org\n\n"
function login.cb_becomeplayer(actor, place, dialog)
actor.kind='P'
actor.Count={} setmetatable(actor.Count,NilIsZero)
actor.food={} setmetatable(actor.food,NilIsZero)
actor.spectra={} setmetatable(actor.spectra,NilIsZero)
actor.stack={}
actor.team='red'
tangible.setclass(actor, player)
tangible.animate(actor,{action="warp",plane="main",x=0,y=0,z=0})
end
function login.cb_p123(actor, place, dialog)
print("CB_P123 actor=", actor, " place=", place, " dialog=", dialog);
print(1);
print(2);
print(3);
end
function bechar()
local a = tangible.actor()
tangible.animate(a, nil, {bp="TangibleCharacter", xyz={0,0,90}})
end
makeclass("engio")
function engio.myfunction(actor, place, a, b, c)
print("Myfunction actor=", actor," place=", place)
print("A:", a)
print("B:", b)
print("C:", c)
return {13, "chicken", {2,3,4}, false}
end
function engio.move(actor, place, action, xyz, facing) function engio.move(actor, place, action, xyz, facing)
-- todo: sanity check the parameters. -- todo: sanity check the parameters.

View File

@@ -1,7 +0,0 @@
makeclass('prng')
function prng.seed(n)
ug.set(prngseed,n)
end
function