mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Merge branch 'develop'
This commit is contained in:
@@ -40,7 +40,7 @@ Image=24
|
||||
ButtonCount=3
|
||||
|
||||
;Set the appearance of the elevator
|
||||
MainFrm=148
|
||||
ButtonsFrm=151
|
||||
MainFrm=148 ; EL_VAULT.FRM
|
||||
ButtonsFrm=151 ; EL_MIL3.FRM
|
||||
|
||||
;Set up the exit points for all three buttons (see examples above)
|
||||
|
||||
@@ -21,6 +21,7 @@ CheckLOS=0
|
||||
; 16 - bright yellow
|
||||
; 32 - dark yellow
|
||||
; 64 - purple
|
||||
; You can set a custom color from the game palette by multiplying the color index value by 256 (available since sfall 4.2.7)
|
||||
OutlineColor=16
|
||||
|
||||
; Motion Scanner mode:
|
||||
|
||||
+18
-13
@@ -1,5 +1,5 @@
|
||||
;sfall configuration settings
|
||||
;v4.2.6
|
||||
;v4.2.7
|
||||
|
||||
[Main]
|
||||
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
|
||||
@@ -85,6 +85,7 @@ GPUBlt=0
|
||||
Use32BitHeadGraphics=0
|
||||
|
||||
;Set to 1 to automatically search for alternative avi video files when Fallout tries to play the game movies
|
||||
;Set to 2 to force avi videos to fit the screen width
|
||||
;Requires DX9 graphics mode
|
||||
AllowDShowMovies=0
|
||||
|
||||
@@ -132,8 +133,8 @@ AllowSoundForFloats=0
|
||||
;This does not effect the play_sfall_sound and stop_sfall_sound script functions
|
||||
AllowDShowSound=0
|
||||
|
||||
;Set to 1 to override the music path used by default (i.e. data\sound\music\) if not present in the cfg
|
||||
;Set to 2 to overwrite all occurances of the music path
|
||||
;Set to 1 to override the default music path with data\sound\music\ if music_path is not present in the cfg
|
||||
;Set to 2 to overwrite all occurrences of the music path
|
||||
OverrideMusicDir=1
|
||||
|
||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
@@ -284,7 +285,8 @@ DialogGenderWords=0
|
||||
;FemaleDefaultModel=hfjmps
|
||||
|
||||
;To change the various ingame movies, modify the next 17 lines
|
||||
;Most of these can also be changed ingame via script.
|
||||
;You can also define additional movies by adding Movie18 - Movie32 lines
|
||||
;Most of these can also be changed ingame via script
|
||||
Movie1=iplogo.mve
|
||||
Movie2=intro.mve
|
||||
Movie3=elder.mve
|
||||
@@ -340,7 +342,7 @@ DialogueFix=1
|
||||
;Prevents you from using number keys to enter unvisited areas on a town map
|
||||
TownMapHotkeysFix=1
|
||||
|
||||
;Set to 1 to disable the horrigan encounter
|
||||
;Set to 1 to disable the Horrigan encounter
|
||||
DisableHorrigan=0
|
||||
|
||||
;Set to 1 to disable the random element in NPC levelling.
|
||||
@@ -404,7 +406,7 @@ AlwaysReloadMsgs=0
|
||||
PlayIdleAnimOnReload=0
|
||||
|
||||
;Changes the timer (in days) for deleting corpses on a map after you leave (valid range: 0..13)
|
||||
;The corpses of critters with 'Ages' flag or on maps with 'dead_bodies_age=No' set in maps.txt will not disappear
|
||||
;The corpses of critters with 'Ages' flag set or on maps with 'dead_bodies_age=No' set in maps.txt will not disappear
|
||||
;Default is 6. Set to 0 for a 12-hour timer
|
||||
CorpseDeleteTime=6
|
||||
|
||||
@@ -574,8 +576,8 @@ SuperStimExploitFix=0
|
||||
InventoryApCost=4
|
||||
QuickPocketsApCostReduction=2
|
||||
|
||||
;Set to 1 to allow objects seeing through other objects that have their ShootThru flag set
|
||||
;Note that enabling this option can cause unexpected NPC behavior in some situations
|
||||
;Set to 1 to fix obj_can_see_obj script function to allow critters to see through objects with 'ShootThru' flag set and other critters in front of them
|
||||
;Note that enabling this option can cause unexpected NPC behavior in some cases, e.g. initiating combat or dialogue when the player is behind certain obstacles
|
||||
ObjCanSeeObj_ShootThru_Fix=0
|
||||
|
||||
;Set to 1 to fix the broken obj_can_hear_obj script function
|
||||
@@ -585,11 +587,10 @@ ObjCanHearObjFix=0
|
||||
;If the argument value is -1, the mood will be determined by the local variable 0 of the script (vanilla behavior)
|
||||
StartGDialogFix=0
|
||||
|
||||
;Set to 1 to fix and repurpose the unused called_shot/num_attacks arguments of attack_complex script function
|
||||
;This also changes the behavior of the result flags arguments
|
||||
;called_shot - additional damage, when the damage received by the target is above the specified minimum damage
|
||||
;Set to 1 to fix attacker_results/target_results arguments and repurpose the unused called_shot/num_attacks arguments of attack_complex script function
|
||||
;New behavior of the arguments:
|
||||
;called_shot - additional damage when hitting the target
|
||||
;num_attacks - the number of free action points on the first turn only
|
||||
;attacker_results - unused, must be 0 or not equal to the target_results argument when specifying result flags for the target
|
||||
AttackComplexFix=0
|
||||
|
||||
;Set to 1 to fix the issue with the division operator treating negative integers as unsigned
|
||||
@@ -696,6 +697,10 @@ NumbersInDialogue=0
|
||||
;Set to 1 to use Fallout's normal text font instead of DOS-like font on the world map
|
||||
WorldMapFontPatch=0
|
||||
|
||||
;Set to 1 to use Fallout's normal text font for death screen subtitles
|
||||
;Requires changing the color of subtitles in death.pal palette to white color (index 220) to display the text correctly
|
||||
DeathScreenFontPatch=0
|
||||
|
||||
;Set to 1 to keep the selected attack mode when moving the weapon between active item slots
|
||||
KeepWeaponSelectMode=1
|
||||
|
||||
@@ -831,7 +836,7 @@ DontDeleteProtos=0
|
||||
;Set to 1 to force sfall to inject all hooks code into the game, even if corresponding hook scripts don't exist
|
||||
InjectAllGameHooks=0
|
||||
|
||||
;Set to 1 to force sfall to search for global scripts every time the game loads rather than only once on the first game start
|
||||
;Set to 1 to force sfall to search for global/hook scripts every time the game loads rather than only the first time
|
||||
AlwaysFindScripts=0
|
||||
|
||||
;Set to 1 to force critters to display combat float messages
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
// Status: WIP
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Blur filter setting
|
||||
//
|
||||
// min: blurFalloff 8, sharpness 10/8
|
||||
// mid: blurFalloff 6, sharpness 8
|
||||
// max: blurFalloff 4, sharpness 6
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define blurFalloff 4.0
|
||||
#define sharpness 6.0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Sharpen filter setting
|
||||
//
|
||||
// min: Sharpen 0.5, EdgeSharpen 1.0
|
||||
// mid: Sharpen 1.0, EdgeSharpen -0.25
|
||||
// max: Sharpen 1.75, EdgeSharpen -0.5 (1.5, -0.25)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define Sharpen 0.5
|
||||
#define EdgeSharpen 1.0
|
||||
|
||||
|
||||
texture bloomMap;
|
||||
sampler s0;
|
||||
@@ -12,6 +31,88 @@ sampler BloomSampler : samplerstate
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
// Variables that set the width and height of the current game resolution from sfall
|
||||
float w;
|
||||
float h;
|
||||
|
||||
static const float2 resolution = float2(w, h);
|
||||
static const float2 wPass = float2(1, 0);
|
||||
static const float2 hPass = float2(0, 1);
|
||||
|
||||
float Brightness(float3 color)
|
||||
{
|
||||
return 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
|
||||
}
|
||||
|
||||
float3 BlurFunction(float2 uv, float brightness, inout float totalWeight)
|
||||
{
|
||||
float3 pointColor = (tex2Dlod(s0, float4(uv, 0, 0)).rgb);
|
||||
|
||||
float diff = abs(brightness - Brightness(pointColor));
|
||||
float weight = exp2((-0.25 * blurFalloff) - (diff * sharpness));
|
||||
totalWeight += weight;
|
||||
|
||||
return pointColor * weight;
|
||||
}
|
||||
|
||||
float4 BlurDeltaPassPS(float2 uv : TEXCOORD0, uniform float2 delta) : COLOR0
|
||||
{
|
||||
float3 sumColor = (tex2D(s0, uv).rgb);
|
||||
float brightness = Brightness(sumColor);
|
||||
|
||||
delta *= (1 / resolution);
|
||||
float totalWeight = 1;
|
||||
|
||||
float2 pointUV = uv + delta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
pointUV = uv - delta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
return float4((sumColor / totalWeight), 1);
|
||||
}
|
||||
|
||||
static const float2 wDelta = float2(1, 0) * (1 / resolution);
|
||||
static const float2 hDelta = float2(0, 1) * (1 / resolution);
|
||||
|
||||
float4 BlurPS(float4 color : COLOR0, float2 uv : TEXCOORD0) : COLOR0
|
||||
{
|
||||
float totalWeight = 1;
|
||||
|
||||
float3 sumColor = (tex2D(s0, uv).rgb);
|
||||
float brightness = Brightness(sumColor);
|
||||
|
||||
float2 pointUV = uv + wDelta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
pointUV = uv - wDelta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
pointUV = uv + hDelta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
pointUV = uv - hDelta;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
return float4((sumColor / totalWeight), 1);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Bloom effect setting
|
||||
//
|
||||
// min: BloomIntensity .8
|
||||
// mid: BloomIntensity .85
|
||||
// max: BloomIntensity .9
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define BaseIntensity 1.2
|
||||
#define BaseSaturation 1.0
|
||||
|
||||
#define BloomIntensity 0.8
|
||||
#define BloomSaturation 0.35
|
||||
|
||||
#define BloomThreshold 0.35
|
||||
#define BlurPower 0.002
|
||||
|
||||
// pseudo gauss blur
|
||||
static const float2 offsets[12] = {
|
||||
-0.326212, -0.405805,
|
||||
@@ -28,89 +129,122 @@ static const float2 offsets[12] = {
|
||||
-0.791559, -0.597705,
|
||||
};
|
||||
|
||||
float w;
|
||||
float h;
|
||||
static const float2 resolution = float2(w, h);
|
||||
|
||||
// blur setting
|
||||
static const float blurFalloff = 8;
|
||||
static const float sharpness = 4;
|
||||
|
||||
float4 AdjustSaturation(float4 color, float saturation) {
|
||||
float4 AdjustSaturation(float4 color, float saturation)
|
||||
{
|
||||
float grey = dot(color, float3(0.3, 0.59, 0.11));
|
||||
|
||||
return lerp(grey, color, saturation);
|
||||
}
|
||||
|
||||
float Brightness(float3 color)
|
||||
float4 BloomPS(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
|
||||
{
|
||||
return color.r * color.g - 0.75 * color.b;
|
||||
}
|
||||
|
||||
float3 BlurFunction(float2 uv, float brightness, inout float totalWeight)
|
||||
{
|
||||
float3 pointColor =(tex2Dlod(s0, float4(uv, 0, 0)).rgb);
|
||||
float diff = abs(brightness - Brightness(pointColor));
|
||||
float weight = exp2(-0.25 * blurFalloff - diff * sharpness);
|
||||
totalWeight += weight;
|
||||
|
||||
return pointColor * weight;
|
||||
}
|
||||
|
||||
float4 BlurPS(float2 uv : TEXCOORD0, uniform float2 delta) : COLOR0
|
||||
{
|
||||
float3 sumColor = (tex2D(s0, uv).rgb);
|
||||
float totalWeight = 1;
|
||||
float brightness = Brightness(sumColor);
|
||||
delta *= (1 / resolution);
|
||||
float radius = 1;
|
||||
|
||||
float2 pointUV = uv + delta * radius;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
pointUV = uv - delta * radius;
|
||||
sumColor += BlurFunction(pointUV, brightness, totalWeight);
|
||||
|
||||
return float4((sumColor / totalWeight),1);
|
||||
// return AdjustSaturation(Color, 0.5);
|
||||
}
|
||||
|
||||
float4 BloomT(float2 texCoord : TEXCOORD0) : COLOR0 {
|
||||
float4 c = tex2D(s0, texCoord);
|
||||
float BloomThreshold = 0.2;
|
||||
|
||||
return saturate((c - BloomThreshold) / (1 - BloomThreshold));
|
||||
}
|
||||
|
||||
float4 Bloom(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 {
|
||||
float BaseIntensity = 1.0;
|
||||
float BaseSaturation = 1;
|
||||
float BloomIntensity = 1; // 0.4
|
||||
float BloomSaturation = 0.5;
|
||||
float BlurPower = 0.01;
|
||||
float BloomThreshold = 0.5;
|
||||
|
||||
float4 original = tex2D(s0, texCoord);
|
||||
|
||||
// blur
|
||||
float4 sum = tex2D(s0, texCoord);
|
||||
for(int i = 0; i < 12; i++){
|
||||
sum += tex2D(s0, texCoord + BlurPower * offsets[i]);
|
||||
}
|
||||
sum /= 13;
|
||||
|
||||
original = AdjustSaturation(original, BaseSaturation) * BaseIntensity;
|
||||
sum = AdjustSaturation(sum, BloomSaturation) * BloomIntensity;
|
||||
float sum = (original.r + original.g + original.b) * 0.333;
|
||||
if (sum >= 0.95) return original;
|
||||
|
||||
sum = saturate((sum - BloomThreshold) / (1 - BloomThreshold));
|
||||
// bloom blur
|
||||
float4 bloomBlur = tex2D(s0, texCoord);
|
||||
for(int i = 0; i < 12; i++)
|
||||
{
|
||||
bloomBlur += tex2D(s0, texCoord + BlurPower * offsets[i]);
|
||||
}
|
||||
bloomBlur *= 0.085;
|
||||
|
||||
return sum + original;
|
||||
// return sum;
|
||||
float intensity = BloomIntensity - lerp(0.0, 0.2, sum);
|
||||
bloomBlur = AdjustSaturation(bloomBlur, BloomSaturation) * intensity;
|
||||
bloomBlur = saturate((bloomBlur - BloomThreshold) / (1 - BloomThreshold));
|
||||
|
||||
return bloomBlur + original;
|
||||
}
|
||||
|
||||
technique Blur
|
||||
static const float CoefBlur = (Sharpen * 0.5);
|
||||
static const float CoefOrig = (1 + CoefBlur);
|
||||
|
||||
// for the sharpen edge
|
||||
#define SharpenEdge 0.4
|
||||
static const float sharpenVal0 = (Sharpen * (1.5 + EdgeSharpen));
|
||||
static const float sharpenVal1 = ((sharpenVal0 - 1) / 8.0);
|
||||
|
||||
// pixel "width"
|
||||
static const float px = (1.0 / w);
|
||||
static const float py = (1.0 / h);
|
||||
|
||||
// for the blur filter
|
||||
#define mean 1.0
|
||||
static const float dx = (mean * px);
|
||||
static const float dy = (mean * py);
|
||||
|
||||
float4 SharpenComplexPS(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
|
||||
{
|
||||
// pass P2 { PixelShader = compile ps_2_0 BloomT(); }
|
||||
// pass P3 { PixelShader = compile ps_2_0 Bloom(); }
|
||||
Pass P0 { PixelShader = compile ps_3_0 BlurPS(float2(1, 0)); }
|
||||
Pass P1 { PixelShader = compile ps_3_0 BlurPS(float2(0, 1)); }
|
||||
float4 c0 = tex2D(s0, texCoord); // get original pixel
|
||||
|
||||
// edge detection
|
||||
// Get neighbor points
|
||||
// [ c1, c2, c3 ]
|
||||
// [ c4, c0, c5 ]
|
||||
// [ c6, c7, c8 ]
|
||||
float4 c1 = tex2D(s0, texCoord + float2(-px, -py));
|
||||
float4 c2 = tex2D(s0, texCoord + float2( 0, -py));
|
||||
float4 c3 = tex2D(s0, texCoord + float2( px, -py));
|
||||
float4 c4 = tex2D(s0, texCoord + float2(-px, 0));
|
||||
float4 c5 = tex2D(s0, texCoord + float2( px, 0));
|
||||
float4 c6 = tex2D(s0, texCoord + float2(-px, py));
|
||||
float4 c7 = tex2D(s0, texCoord + float2( 0, py));
|
||||
float4 c8 = tex2D(s0, texCoord + float2( px, py));
|
||||
|
||||
// using Sobel filter
|
||||
// horizontal gradient
|
||||
// [ -1, 0, 1 ]
|
||||
// [ -2, 0, 2 ]
|
||||
// [ -1, 0, 1 ]
|
||||
float delta1 = (c3 + 2 * c5 + c8) - (c1 + 2 * c4 + c6);
|
||||
|
||||
// vertical gradient
|
||||
// [ -1, - 2, -1 ]
|
||||
// [ 0, 0, 0 ]
|
||||
// [ 1, 2, 1 ]
|
||||
float4 c13 = c1 + c3;
|
||||
float4 c68 = c6 + c8;
|
||||
float delta2 = (c68 + 2 * c7) - (c13 + 2 * c2);
|
||||
|
||||
// computation
|
||||
if (sqrt(mul(delta1, delta1) + mul(delta2, delta2)) > SharpenEdge) {
|
||||
// if we have an edge, use sharpen
|
||||
return c0 * sharpenVal0 - (c13 + c2 + c4 + c5 + c68 + c7) * sharpenVal1;
|
||||
|
||||
// Display edges in red...
|
||||
//return float4( 1.0, 0.0, 0.0, 0.0 );
|
||||
} else {
|
||||
// else return corrected image
|
||||
|
||||
// compute blurred image (gaussian filter)
|
||||
c1 = tex2D(s0, texCoord + float2(-dx, -dy));
|
||||
c2 = tex2D(s0, texCoord + float2( 0, -dy));
|
||||
c3 = tex2D(s0, texCoord + float2( dx, -dy));
|
||||
c4 = tex2D(s0, texCoord + float2(-dx, 0));
|
||||
c5 = tex2D(s0, texCoord + float2( dx, 0));
|
||||
c6 = tex2D(s0, texCoord + float2(-dx, dy));
|
||||
c7 = tex2D(s0, texCoord + float2( 0, dy));
|
||||
c8 = tex2D(s0, texCoord + float2( dx, dy));
|
||||
|
||||
// gaussian filter
|
||||
// [ 1, 2, 1 ]
|
||||
// [ 2, 4, 2 ]
|
||||
// [ 1, 2, 1 ]
|
||||
// to normalize the values, we need to divide by the coeff sum
|
||||
float4 flou = (c1 + c3 + c6 + c8 + 2 * (c2 + c4 + c5 + c7) + 4 * c0) * 0.0625; // 1 / (1+2+1+2+4+2+1+2+1) = 1 / 16 = 0.0625
|
||||
|
||||
// substract blurred image from original image
|
||||
return (CoefOrig * c0 - CoefBlur * flou);
|
||||
}
|
||||
}
|
||||
|
||||
technique BlurBloom
|
||||
{
|
||||
//pass P0 { PixelShader = compile ps_3_0 BlurDeltaPassPS(wPass); }
|
||||
//pass P1 { PixelShader = compile ps_3_0 BlurDeltaPassPS(hPass); }
|
||||
|
||||
pass P0 { PixelShader = compile ps_3_0 BlurPS(); }
|
||||
pass P3 { PixelShader = compile ps_2_0 BloomPS(); }
|
||||
pass P2 { PixelShader = compile ps_2_0 SharpenComplexPS(); }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/*
|
||||
Example implementation of the algorithm of how the game engine checks if one critter sees another critter.
|
||||
|
||||
NOTE: the AllowUnsafeScripting option must be enabled.
|
||||
*/
|
||||
|
||||
#include "..\headers\define.h"
|
||||
@@ -9,10 +7,8 @@
|
||||
#include "..\headers\sfall\sfall.h"
|
||||
#include "..\headers\sfall\define_extra.h"
|
||||
|
||||
#define can_see_(source, target) call_offset_r2(0x412BEC, source, target)
|
||||
#define obj_dist_(target, source) call_offset_r2(0x48BBD4, target, source)
|
||||
|
||||
procedure start;
|
||||
procedure can_see(variable obj1, variable obj2);
|
||||
|
||||
procedure start begin
|
||||
if game_loaded then begin
|
||||
@@ -21,40 +17,50 @@ procedure start begin
|
||||
variable
|
||||
source := get_sfall_arg,
|
||||
target := get_sfall_arg,
|
||||
original := get_sfall_arg,
|
||||
hookType := get_sfall_arg, /* new arg */
|
||||
engine := get_sfall_arg,
|
||||
type := get_sfall_arg, /* new arg */
|
||||
result := 0,
|
||||
distance;
|
||||
distance, seeDistance, seeText;
|
||||
|
||||
if target then begin
|
||||
distance := get_critter_stat(source, STAT_pe);
|
||||
seeDistance := get_critter_stat(source, STAT_pe);
|
||||
|
||||
if can_see_(source, target) then begin
|
||||
distance *= 5;
|
||||
if (get_flags(target) bwand FLAG_TRANSGLASS) then distance /= 2;
|
||||
if can_see(source, target) then begin
|
||||
seeDistance *= 5;
|
||||
if (get_flags(target) bwand FLAG_TRANSGLASS) then seeDistance /= 2;
|
||||
end else if combat_is_initialized then begin
|
||||
distance *= 2;
|
||||
seeDistance *= 2;
|
||||
end
|
||||
|
||||
if (target == dude_obj) then begin
|
||||
if sneak_success then begin
|
||||
distance /= 4;
|
||||
if has_skill(target, SKILL_SNEAK) > 120 then distance -= 1;
|
||||
seeDistance /= 4;
|
||||
if has_skill(target, SKILL_SNEAK) > 120 then seeDistance -= 1;
|
||||
end else if dude_is_sneaking then begin
|
||||
distance := distance * 2 / 3;
|
||||
seeDistance := (seeDistance * 2) / 3; // distance div 1.5
|
||||
end
|
||||
end
|
||||
|
||||
if obj_dist_(target, source) <= distance then result := 1;
|
||||
distance := tile_distance_objs(source, target);
|
||||
if (get_flags(source) bwand FLAG_MULTIHEX) then distance--;
|
||||
if (get_flags(target) bwand FLAG_MULTIHEX) then distance--;
|
||||
|
||||
// example
|
||||
if (result) then begin
|
||||
display_msg("hs_withinperception: " + obj_name(source) + " sees " + obj_name(target) + " [original: " + original + " script: " + result + "]");
|
||||
end else begin
|
||||
display_msg("hs_withinperception: " + obj_name(source) + " does not see " + obj_name(target) + " [original: " + original + " script: " + result + "]");
|
||||
end
|
||||
if (distance <= seeDistance) then result := 1;
|
||||
|
||||
seeText = " does not see > ";
|
||||
if (result) then seeText = " sees > ";
|
||||
|
||||
// Example
|
||||
display_msg("hs_withinperception: " + obj_name(source) + seeText + obj_name(target) + " [engine: " + engine + ", script: " + result + "]");
|
||||
|
||||
/* override engine result */
|
||||
//set_sfall_return(result);
|
||||
end
|
||||
|
||||
//set_sfall_return(result);
|
||||
end
|
||||
end
|
||||
|
||||
procedure can_see(variable obj1, variable obj2) begin
|
||||
variable dir = obj_get_rot(obj1) - rotation_to_tile(tile_num(obj1), tile_num(obj2));
|
||||
if (dir < 0) then dir = -dir;
|
||||
return (dir <= 1) or (dir == 5);
|
||||
end
|
||||
|
||||
@@ -340,6 +340,9 @@ There are several changes in this version of sslc which may result in problems f
|
||||
=== Changelog ===
|
||||
=================
|
||||
|
||||
> sfall 4.2.7
|
||||
- added ability to declare local variables anywhere in the procedure body
|
||||
|
||||
> sfall 4.2.3
|
||||
- fixed compiler giving "assignment operator expected" error when a variable-like macro is not being defined properly
|
||||
- added new logical operators "AndAlso", "OrElse" for short-circuit evaluation of logical expressions
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#ifndef DEFINE_EXTRA_H
|
||||
#define DEFINE_EXTRA_H
|
||||
|
||||
/* Combat Flags */
|
||||
#define DAM_PRESERVE_FLAGS 0x80000000 // keep the existing result flags when setting new flags in attack_complex (for sfall)
|
||||
|
||||
#define BODY_HIT_HEAD (0)
|
||||
#define BODY_HIT_LEFT_ARM (1)
|
||||
#define BODY_HIT_RIGHT_ARM (2)
|
||||
|
||||
@@ -262,8 +262,8 @@
|
||||
#define party_member_list_all party_member_list(1)
|
||||
|
||||
// fake perks/traits add mode flags
|
||||
#define ADD_PERK_MODE_TRAIT (1) // add to the player's traits
|
||||
#define ADD_PERK_MODE_PERK (2) // add to the player's perks
|
||||
#define ADD_PERK_MODE_TRAIT (1) // add to the player's traits list
|
||||
#define ADD_PERK_MODE_PERK (2) // add to the player's perks list
|
||||
#define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks (after added to the player)
|
||||
|
||||
// instantly apply the item to dude_obj (w/o animation)
|
||||
@@ -273,11 +273,19 @@
|
||||
set_self(0)
|
||||
|
||||
// returns the corrected tile distance between two objects to the distance variable (return value >= 9996 is an error when getting the distance)
|
||||
#define distance_objs(distance, obj1, obj2) distance := tile_distance_objs(obj1, obj2) - 1; \
|
||||
if (get_flags(obj1) bwand FLAG_MULTIHEX) distance--; \
|
||||
if (get_flags(obj2) bwand FLAG_MULTIHEX) distance--
|
||||
#define distance_objs(distance, obj1, obj2) distance := tile_distance_objs(obj1, obj2) - 1; \
|
||||
if (get_flags(obj1) bwand FLAG_MULTIHEX) then distance--; \
|
||||
if (get_flags(obj2) bwand FLAG_MULTIHEX) then distance--
|
||||
|
||||
// sfall_funcX macros
|
||||
|
||||
/* sfall metarule3 function macros */
|
||||
// sets the number of days (range 1...127) for the Frank Horrigan encounter, or disable the encounter if days is set to 0
|
||||
#define set_horrigan_days(day) metarule3(200, day, 0, 0)
|
||||
// clears the keyboard input buffer, use it in the HOOK_KEYPRESS hook to clear keyboard events before calling functions that are waiting for keyboard input
|
||||
#define clear_keyboard_buffer metarule3(201, 0, 0, 0)
|
||||
|
||||
|
||||
/* sfall_funcX macros */
|
||||
#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name)
|
||||
#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam)
|
||||
#define add_iface_tag sfall_func0("add_iface_tag")
|
||||
|
||||
@@ -432,8 +432,9 @@ Some utility/math functions are available:
|
||||
- gets the current outline color for an object
|
||||
|
||||
> void sfall_func2("set_outline", object, int color)
|
||||
- sets the outline color of an object
|
||||
- 0 means or any value above 0x00FFFFFF disables the outline
|
||||
- sets the outline color of an object (see OUTLINE_* constants in sfall.h)
|
||||
- can also set a custom color from the game palette by shifting the color index value left by 8 bits: 0xCC00 where CC is the palette index (available since sfall 4.2.7/3.8.27)
|
||||
- passing 0 will disable the outline
|
||||
- call "tile_refresh_display" after changing outline of objects to properly redraw the scene
|
||||
|
||||
> int sfall_func1("get_flags", object)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
[sfall]
|
||||
SaveInCombat=目前不能存档。
|
||||
KarmaGain=你获得了%d点道德。
|
||||
KarmaLoss=你失去了%d点道德。
|
||||
HighlightFail1=你没有携带动态感应器。
|
||||
HighlightFail2=你的动态感应器没电了。
|
||||
SuperStimExploitMsg=你不能对没受伤的人使用超级治疗针!
|
||||
BlockedCombat=你现在不能进入战斗。
|
||||
SaveSfallDataFail=储存存档延展信息时发生错误!检查是否有其他程序占用存档文件/文件夾之后再试一次。
|
||||
PartyLvlMsg=等级:
|
||||
PartyACMsg=AC:
|
||||
PartyAddictMsg=上瘾
|
||||
NPCPickupFail=%s无法将东西捡起来。
|
||||
|
||||
[AppearanceMod]
|
||||
RaceText=种族
|
||||
StyleText=风格
|
||||
DoneBtn=完成
|
||||
@@ -0,0 +1,18 @@
|
||||
[sfall]
|
||||
SaveInCombat=目前不能存檔。
|
||||
KarmaGain=你獲得了%d點道德。
|
||||
KarmaLoss=你失去了%d點道德。
|
||||
HighlightFail1=你沒有攜帶動態感應器。
|
||||
HighlightFail2=你的動態感應器沒電了。
|
||||
SuperStimExploitMsg=你不能對沒受傷的角色使用超級治療針!
|
||||
BlockedCombat=你現在不能進入戰鬥。
|
||||
SaveSfallDataFail=儲存存檔延伸資訊時發生錯誤!檢查是否有其他程式占用存檔檔案/資料夾之後再試一次。
|
||||
PartyLvlMsg=等級:
|
||||
PartyACMsg=AC:
|
||||
PartyAddictMsg=上癮
|
||||
NPCPickupFail=%s無法將東西撿起來。
|
||||
|
||||
[AppearanceMod]
|
||||
RaceText=種族
|
||||
StyleText=風格
|
||||
DoneBtn=完成
|
||||
@@ -0,0 +1,18 @@
|
||||
[sfall]
|
||||
SaveInCombat=Tu ne peux pas sauvegarder en ce moment.
|
||||
KarmaGain=Tu gagnes %d Karma.
|
||||
KarmaLoss=Tu perds %d Karma.
|
||||
HighlightFail1=Tu n'as pas de détecteur de mouvement.
|
||||
HighlightFail2=Ton détecteur de mouvement n'a plus de charges.
|
||||
SuperStimExploitMsg=You cannot use a super stim on someone who is not injured!
|
||||
BlockedCombat=You cannot enter combat at this time.
|
||||
SaveSfallDataFail=ERROR saving extended savegame information! Check if other programs interfere with savegame files/folders and try again.
|
||||
PartyLvlMsg=Suiv:
|
||||
PartyACMsg=TA:
|
||||
PartyAddictMsg=Dependance
|
||||
NPCPickupFail=%s ne peut pas ramasser l'objet.
|
||||
|
||||
[AppearanceMod]
|
||||
RaceText=Race
|
||||
StyleText=Style
|
||||
DoneBtn=Fait
|
||||
@@ -0,0 +1,18 @@
|
||||
[sfall]
|
||||
SaveInCombat=Momentan kein Speichern möglich.
|
||||
KarmaGain=Du erhältst %d Karma.
|
||||
KarmaLoss=Du verlierst %d Karma.
|
||||
HighlightFail1=Du trägst keinen Bewegungssensor.
|
||||
HighlightFail2=Dein Bewegungssensor ist entladen.
|
||||
SuperStimExploitMsg=Du kannst einem Unverletzten kein Super-Stimpak verabreichen!
|
||||
BlockedCombat=Kampfmodus momentan nicht verfügbar.
|
||||
SaveSfallDataFail=FEHLER beim Speichern des Spielstandes! Prüfe, ob andere Programme darauf zugreifen und probiere es erneut.
|
||||
PartyLvlMsg=Lvl:
|
||||
PartyACMsg=RÜ:
|
||||
PartyAddictMsg=Abhäng
|
||||
NPCPickupFail=%s kann das Objekt nicht nehmen.
|
||||
|
||||
[AppearanceMod]
|
||||
RaceText=Geschlecht
|
||||
StyleText=Stil
|
||||
DoneBtn=OK
|
||||
@@ -0,0 +1,18 @@
|
||||
[sfall]
|
||||
SaveInCombat=Сохранение в данный момент невозможно.
|
||||
KarmaGain=Вы получаете %d единиц кармы.
|
||||
KarmaLoss=Вы теряете %d единиц кармы.
|
||||
HighlightFail1=Сенсор движения недоступен.
|
||||
HighlightFail2=Сенсор движения разряжен.
|
||||
SuperStimExploitMsg=Вы не можете использовать суперстимулятор на здоровом персонаже!
|
||||
BlockedCombat=Вы не можете сейчас начать бой.
|
||||
SaveSfallDataFail=ОШИБКА записи расширенной информации! Убедитесь что другие программы не обращаются к файлам/каталогам сохраняемой игры и попробуйте еще раз.
|
||||
PartyLvlMsg=Ур.:
|
||||
PartyACMsg=КБ:
|
||||
PartyAddictMsg=Зависимость
|
||||
NPCPickupFail=%s не может подобрать предмет.
|
||||
|
||||
[AppearanceMod]
|
||||
RaceText=Раса
|
||||
StyleText=Стиль
|
||||
DoneBtn=Закрыть
|
||||
@@ -10,11 +10,12 @@ namespace sfall
|
||||
std::multimap<long, long> writeAddress;
|
||||
|
||||
static std::vector<long> excludeWarning = {
|
||||
0x44E949, 0x44E94A, 0x44E937, 0x4F5F40, 0x4CB850, // from movies.cpp
|
||||
0x44E949, 0x44E94A, 0x44E937, 0x4F5F40, // from movies.cpp
|
||||
};
|
||||
|
||||
static std::vector<long> excludeConflict = {
|
||||
0x42A0F8, // bugfixes.cpp
|
||||
0x42A0F8, // bugfixes.cpp
|
||||
0x461495, // BarBoxes.cpp
|
||||
};
|
||||
|
||||
struct HackPair {
|
||||
@@ -76,7 +77,7 @@ static std::vector<HackPair> hackAddr = {
|
||||
{0x484B18, 1}, {0x484B19, 4}, // hookcall
|
||||
// module: Movies
|
||||
{0x44E937, 1}, {0x44E938, 4}, {0x44E949, 1}, {0x44E94A, 4}, // hookcalls
|
||||
{0x4F5F40, 1}, {0x4CB850, 1},
|
||||
{0x4F5F40, 1},
|
||||
// module: Objects
|
||||
{0x4A364A, 5}, {0x4831D9, 1}, {0x4831DA, 1},
|
||||
{0x4841D6, 1}, {0x4841D7, 4}, // hookcall
|
||||
|
||||
@@ -68,7 +68,7 @@ bool CritterCopyProto(long pid, long* &proto_dst) {
|
||||
proto_dst = nullptr;
|
||||
return false;
|
||||
}
|
||||
proto_dst = reinterpret_cast<long*>(new int32_t[104]);
|
||||
proto_dst = reinterpret_cast<long*>(new long[104]);
|
||||
memcpy(proto_dst, protoPtr, 416);
|
||||
return true;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ long GetScriptLocalVars(long sid) {
|
||||
// Returns window ID by x/y coordinate (hidden windows are ignored)
|
||||
long __fastcall GetTopWindowID(long xPos, long yPos) {
|
||||
fo::Window* win = nullptr;
|
||||
long countWin = *(DWORD*)FO_VAR_num_windows - 1;
|
||||
long countWin = fo::var::num_windows - 1;
|
||||
for (int n = countWin; n >= 0; n--) {
|
||||
win = fo::var::window[n];
|
||||
if (xPos >= win->wRect.left && xPos <= win->wRect.right && yPos >= win->wRect.top && yPos <= win->wRect.bottom) {
|
||||
@@ -393,6 +393,24 @@ void DrawToSurface(long width, long height, long fromX, long fromY, long fromWid
|
||||
}
|
||||
}
|
||||
|
||||
// Fills the specified non-scripted interface window with black color
|
||||
void ClearWindow(DWORD winID, bool refresh) {
|
||||
__asm {
|
||||
xor ebx, ebx;
|
||||
push ebx;
|
||||
mov eax, winID;
|
||||
call fo::funcoffs::win_height_;
|
||||
push eax;
|
||||
mov eax, winID;
|
||||
call fo::funcoffs::win_width_;
|
||||
mov ecx, eax;
|
||||
mov edx, ebx;
|
||||
mov eax, winID;
|
||||
call fo::funcoffs::win_fill_;
|
||||
}
|
||||
if (refresh) fo::func::win_draw(winID);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// print text to surface
|
||||
void PrintText(char* displayText, BYTE colorIndex, DWORD xPos, DWORD yPos, DWORD txtWidth, DWORD toWidth, BYTE* toSurface) {
|
||||
@@ -505,7 +523,16 @@ void RedrawObject(GameObject* obj) {
|
||||
func::tile_refresh_rect(&rect, obj->elevation);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////UNLISTED FRM FUNCTIONS////////////////////////////////////////////////////////////////////////
|
||||
// Redraws all interface windows
|
||||
void RefreshGNW() {
|
||||
*(DWORD*)FO_VAR_doing_refresh_all = 1;
|
||||
for (size_t i = 0; i < fo::var::num_windows; i++) {
|
||||
func::GNW_win_refresh(fo::var::window[i], &fo::var::scr_size, 0);
|
||||
}
|
||||
*(DWORD*)FO_VAR_doing_refresh_all = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////UNLISTED FRM FUNCTIONS//////////////////////////////////////////////////////////////
|
||||
|
||||
static bool LoadFrmHeader(UnlistedFrm *frmHeader, fo::DbFile* frmStream) {
|
||||
if (fo::func::db_freadInt(frmStream, &frmHeader->version) == -1)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
@@ -103,6 +104,9 @@ void DrawToSurface(long width, long height, long fromX, long fromY, long fromWid
|
||||
|
||||
void DrawToSurface(long width, long height, long fromX, long fromY, long fromWidth, BYTE* fromSurf, long toX, long toY, long toWidth, long toHeight, BYTE* toSurf);
|
||||
|
||||
// Fills the specified non-scripted interface window with black color
|
||||
void ClearWindow(DWORD winID, bool refresh = true);
|
||||
|
||||
// Print text to surface
|
||||
void PrintText(char* displayText, BYTE colorIndex, DWORD xPos, DWORD yPos, DWORD txtWidth, DWORD toWidth, BYTE* toSurface);
|
||||
void PrintTextFM(char* displayText, BYTE colorIndex, DWORD xPos, DWORD yPos, DWORD txtWidth, DWORD toWidth, BYTE* toSurface);
|
||||
@@ -130,6 +134,9 @@ DWORD GetMaxCharWidth();
|
||||
// Redraw the given object on screen (does not always redraws the whole object)
|
||||
void RedrawObject(GameObject* obj);
|
||||
|
||||
// Redraws all interface windows
|
||||
void RefreshGNW();
|
||||
|
||||
UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
|
||||
|
||||
}
|
||||
|
||||
+34
-33
@@ -117,50 +117,51 @@ enum CritterFlags : long
|
||||
NoKnockBack = 0x4000, // Can't be knocked back
|
||||
};
|
||||
|
||||
enum DamageFlag : long
|
||||
enum DamageFlag : unsigned long
|
||||
{
|
||||
DAM_KNOCKED_OUT = 0x1,
|
||||
DAM_KNOCKED_DOWN = 0x2,
|
||||
DAM_CRIP_LEG_LEFT = 0x4,
|
||||
DAM_CRIP_LEG_RIGHT = 0x8,
|
||||
DAM_CRIP_ARM_LEFT = 0x10,
|
||||
DAM_CRIP_ARM_RIGHT = 0x20,
|
||||
DAM_BLIND = 0x40,
|
||||
DAM_DEAD = 0x80,
|
||||
DAM_HIT = 0x100,
|
||||
DAM_CRITICAL = 0x200,
|
||||
DAM_ON_FIRE = 0x400,
|
||||
DAM_BYPASS = 0x800,
|
||||
DAM_EXPLODE = 0x1000,
|
||||
DAM_DESTROY = 0x2000,
|
||||
DAM_DROP = 0x4000,
|
||||
DAM_LOSE_TURN = 0x8000,
|
||||
DAM_HIT_SELF = 0x10000,
|
||||
DAM_LOSE_AMMO = 0x20000,
|
||||
DAM_DUD = 0x40000,
|
||||
DAM_HURT_SELF = 0x80000,
|
||||
DAM_RANDOM_HIT = 0x100000,
|
||||
DAM_CRIP_RANDOM = 0x200000,
|
||||
DAM_BACKWASH = 0x400000,
|
||||
DAM_KNOCKED_OUT = 0x1,
|
||||
DAM_KNOCKED_DOWN = 0x2,
|
||||
DAM_CRIP_LEG_LEFT = 0x4,
|
||||
DAM_CRIP_LEG_RIGHT = 0x8,
|
||||
DAM_CRIP_ARM_LEFT = 0x10,
|
||||
DAM_CRIP_ARM_RIGHT = 0x20,
|
||||
DAM_BLIND = 0x40,
|
||||
DAM_DEAD = 0x80,
|
||||
DAM_HIT = 0x100,
|
||||
DAM_CRITICAL = 0x200,
|
||||
DAM_ON_FIRE = 0x400,
|
||||
DAM_BYPASS = 0x800,
|
||||
DAM_EXPLODE = 0x1000,
|
||||
DAM_DESTROY = 0x2000,
|
||||
DAM_DROP = 0x4000,
|
||||
DAM_LOSE_TURN = 0x8000,
|
||||
DAM_HIT_SELF = 0x10000,
|
||||
DAM_LOSE_AMMO = 0x20000,
|
||||
DAM_DUD = 0x40000,
|
||||
DAM_HURT_SELF = 0x80000,
|
||||
DAM_RANDOM_HIT = 0x100000,
|
||||
DAM_CRIP_RANDOM = 0x200000,
|
||||
DAM_BACKWASH = 0x400000,
|
||||
DAM_PERFORM_REVERSE = 0x800000,
|
||||
DAM_PRESERVE_FLAGS = 0x80000000 // sfall, used for attack_complex
|
||||
};
|
||||
|
||||
enum DamageType
|
||||
{
|
||||
DMG_normal = 0,
|
||||
DMG_laser = 1,
|
||||
DMG_fire = 2,
|
||||
DMG_plasma = 3,
|
||||
DMG_electrical = 4,
|
||||
DMG_emp = 5,
|
||||
DMG_explosion = 6,
|
||||
DMG_normal = 0,
|
||||
DMG_laser = 1,
|
||||
DMG_fire = 2,
|
||||
DMG_plasma = 3,
|
||||
DMG_electrical = 4,
|
||||
DMG_emp = 5,
|
||||
DMG_explosion = 6,
|
||||
DMG_BYPASS_ARMOR = 256,
|
||||
DMG_NOANIMATE = 512,
|
||||
DMG_NOANIMATE = 512,
|
||||
};
|
||||
|
||||
enum Gender
|
||||
{
|
||||
GENDER_MALE = 0,
|
||||
GENDER_MALE = 0,
|
||||
GENDER_FEMALE = 1,
|
||||
};
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace fo
|
||||
namespace func
|
||||
{
|
||||
|
||||
// Prints debug message to debug.log file for develop build
|
||||
// Prints debug message to game debug.log file for develop build
|
||||
#ifndef NDEBUG
|
||||
void __declspec(naked) dev_printf(const char* fmt, ...) {
|
||||
__asm jmp fo::funcoffs::debug_printf_;
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace fo
|
||||
namespace func
|
||||
{
|
||||
|
||||
// Prints debug message to debug.log file for develop build
|
||||
#ifndef NDEBUG
|
||||
// Prints debug message to game debug.log file for develop build
|
||||
void dev_printf(const char* fmt, ...);
|
||||
#else
|
||||
void dev_printf(...);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user