|
0 registered members (),
14,965
guests, and 2
spiders. |
|
Key:
Admin,
Global Mod,
Mod
|
|
|
|
Yesterday at 05:32
Enjoy, and Improve the Strategy.
259
98,179
Read More
|
|
|
10/05/26 15:15
I have purchased a monthly subscription for Zorro, but I didn't receive any subscription key to activate it.
May I know how to proceed? Thanks.
1
35
Read More
|
|
|
10/05/26 12:12
You'll get a license key that unlocks the A8 demo version to a full version.
10
1,744
Read More
|
|
|
10/05/26 12:02
I readily believe that you get gaps and bad results with your settings. Unless you trade on the Moscow stock exchange, better use the default weekend and time zone for currencies. Their weekend begins with market close in New York and ends at market open in Sydney. Even if your broker has weekend bars of currencies, they are not from regular trading, and better don't use them for a strategy.
1
127
Read More
|
|
|
10/03/26 14:42
// ---- Real-trade scan buffers: rebuilt every bar, nothing carried ---- [R-33] #define SCAN_NA 16 // [R-33] max assets in the list #define SCAN_W 4 // [R-33] events kept per asset and bar int ScanFillN[SCAN_NA], ScanClsN[SCAN_NA]; var ScanFillID[64], ScanFillDir[64], ScanFillPx[64]; // [R-33] 64 = SCAN_NA * SCAN_W var ScanClsID[64], ScanClsPx[64]; int FltBars = 0, FltGreen = 0; // [R-22] filter census, trace only
// [R-33] Index of an asset in the list, -1 if absent. int scanIdx(string Name) { int i; for(i = 0; i < NumAssetsListed; i++) if(strcmp(Name, Assets[i]) == 0) return i; return -1; }
// [R-33] Slot of this bar's fill on asset k in direction Dir, -1 if none. int scanFill(int k, int Dir) { int j; for(j = 0; j < ScanFillN[k]; j++) if(j < SCAN_W && ScanFillDir[k*SCAN_W + j] == Dir) return j; return -1; }
// [R-33] Slot of this bar's close of trade ID on asset k, -1 if none. int scanCls(int k, var ID) { int j; for(j = 0; j < ScanClsN[k]; j++) if(j < SCAN_W && ScanClsID[k*SCAN_W + j] == ID) return j; return -1; }
// [R-28] Classify a closed signal by its move before costs, signed by direction. // [R-28] A move of exactly zero changes nothing. void classify(vars PrevLoss, vars HaveHist, int Dir, int How, var Move) { printf("\n@SIG,%s,%i,%i,%i,%.8f", Asset, (int)Bar, Dir, How, (var)Move); // [R-28] trace if(Move < 0) { PrevLoss[0] = 1; HaveHist[0] = 1; } else if(Move > 0) { PrevLoss[0] = 0; HaveHist[0] = 1; } }
function run() { // ---- Engine / mode setup ---------------------------------- [R-01..R-05] BarPeriod = 1440; // [R-01] daily bars BarOffset = 940; // [R-01] bar starts 15:40 in the bar time zone set(LOGFILE); // [R-03] export logs and statistics files set(TICKS); // [R-02] tick-precise intrabar simulation (D021) Verbose = 3; // [R-03] skipped trades + parameter errors // !! [R-03] Warning 047 verbosity is OBSERVED, not documented -- see 3.1.
// ---- Data source ------------------------------------------------ [R-04] // !! [R-04] '*' reads the year files but keeps Zorro's silent bare-file // !! fallback; the AssetFirstBar preflight below is the only control on it. History = "put your \\Zorro\\History\\*.t6"; // [R-04] NumYears = 20; // [R-05] simulation window EndDate = 20261001; // [R-05] window end pinned (D029 Add. 3)
// ---- Parameter block -------------- [R-07, R-08, R-24, R-26, R-27, R-31] int EntryDays = 20; // [R-07] System 1 entry channel, trading days int ExitDays = 10; // [R-07] System 1 exit channel, trading days int FailDays = 55; // [R-07] failsafe entry channel, trading days int NPeriod = 20; // [R-26] N = average true range over 20 days var StopMult = 2.0; // [R-27] hard stop at 2N from the fill price int BreakTicks = 1; // [R-08] strict break: price increments beyond the level
// ---- Warm-up ---------------------------------------------- [R-09, R-26] LookBack = 70; // [R-09] covers 55-day channel and 20-day N UnstablePeriod = 40; // [R-26] recursive TA-Lib indicators re-run over 40 bars
// ---- Order handling ------------------------------------- [R-10..R-13] EntryTime = 2; // [R-11] pending order lifetime, bars. INERT (see R-18) Fill = 2; // [R-12] alternative order filling (D023) Hedge = 0; // [R-13] netting by ASSET, not by algo
// ---- Universe --------------------------------------------------- [R-06] if(is(INITRUN)) assetList("AssetsDryRunP7"); // [R-06] frozen P7 (D019)
MaxLong = 1; // [R-10] one position per side per asset MaxShort = 1; // [R-10] magnitude live, sign inert (see R-18)
// ---- Real-trade scan: this bar's fills and closes ------------- [R-33] // [R-33] Above the asset loop: enumeration loops cannot be nested. int si, sk, ss; for(si = 0; si < SCAN_NA; si++) { ScanFillN[si] = 0; ScanClsN[si] = 0; } for(past_trades) { if(TradeID != 0) { sk = scanIdx(TradeAsset); if(sk >= 0) { // !! [R-33] TradeInt is 0 on a new trade: OBSERVED, not documented. if(TradeInt[15] == 0) { // [R-33] fill not seen yet TradeInt[15] = 1; if(ScanFillN[sk] < SCAN_W) { ss = sk*SCAN_W + ScanFillN[sk]; ScanFillID[ss] = TradeID; ScanFillDir[ss] = ifelse(TradeIsLong, 1, -1); ScanFillPx[ss] = TradePriceOpen; } ScanFillN[sk] += 1; } if(TradeIsClosed && TradeInt[14] == 0) { // [R-33] close not seen yet TradeInt[14] = 1; if(ScanClsN[sk] < SCAN_W) { ss = sk*SCAN_W + ScanClsN[sk]; ScanClsID[ss] = TradeID; ScanClsPx[ss] = TradePriceClose; } ScanClsN[sk] += 1; } } } } if(is(EXITRUN)) printf("\n@FGR,%i,%i", FltGreen, FltBars); // [R-22] filter census, trace only
for(listed_assets) { // [R-25] for(listed_assets) only assigns Asset; it does not select. if(!asset(Asset)) continue;
// [R-04] Reject any asset whose history does not cover the window. if(AssetFirstBar > 0) { printf("\n SKIP %s -- history starts at bar %i/%i", Asset, (int)AssetFirstBar, (int)NumBars); continue; }
// [R-08] Read PIP inside the loop: it is an asset-specific parameter. var BreakOffset = BreakTicks * PIP;
// ---- Price series ------------------------------------------------ vars H = series(priceHigh()); vars L = series(priceLow());
// ---- Rolling trading-day channels ------------------ [R-15, R-25] // [R-25] Per-asset state lives in series(), NEVER in a bare static. // [R-15] Carried as series so the code can read the level that was // actually RESTING during a given bar -- see R-16. vars ChEntryHigh = series(0), ChEntryLow = series(0); vars ChExitLow = series(0), ChExitHigh = series(0); vars ChFailHigh = series(0), ChFailLow = series(0);
ChEntryHigh[0] = MaxVal(H, EntryDays); // 20-day high ChEntryLow[0] = MinVal(L, EntryDays); // 20-day low ChExitLow[0] = MinVal(L, ExitDays); // 10-day low ChExitHigh[0] = MaxVal(H, ExitDays); // 10-day high ChFailHigh[0] = MaxVal(H, FailDays); // 55-day high ChFailLow[0] = MinVal(L, FailDays); // 55-day low
// ---- Volatility primitive N -------------------------------- [R-26] vars N = series(ATR(NPeriod));
// ---- Warm-up counter ---------------------------------------- [R-09] vars BarsSeen = series(0); BarsSeen[0] = BarsSeen[1] + 1;
// ---- Shadow-tracker series -------------------- [R-22, R-25, R-28] // [R-25] Created ABOVE the warm-up gate: series() calls must never be // skipped by a bar-varying condition. Only their [0] elements are set // conditionally, further down. vars ShDir = series(0); // shadow signal: 0 none, +1 long, -1 short vars ShEntry = series(0); // shadow entry price (level + break offset) vars ShAdv = series(0); // [R-28] the 2N adverse level, fixed at signal vars PrevLoss = series(0); // 1 = last CLOSED shadow signal was a loser vars HaveHist = series(0); // 1 = at least one shadow signal has closed
ShDir[0] = ShDir[1]; ShEntry[0] = ShEntry[1]; ShAdv[0] = ShAdv[1]; PrevLoss[0] = PrevLoss[1]; HaveHist[0] = HaveHist[1];
// ---- Real-trade link series ---------------------------- [R-33, R-25] vars TrkID = series(0); // [R-33] real trade tied to the open signal, 0 none vars PlL = series(0); // [R-33] 1 = a 20-day long entry rested this bar vars PlS = series(0); // [R-33] 1 = a 20-day short entry rested this bar TrkID[0] = TrkID[1];
// [R-09] Warm-up gate. Every series() call for this asset is ABOVE it. if(BarsSeen[0] < 70) continue;
// ---- Level-or-distance preflight -------------------- [R-17, R-32] var HalfPrice = 0.5 * priceClose(); bool badEntryHigh = (ChEntryHigh[0] < HalfPrice); bool badEntryLow = (ChEntryLow[0] < HalfPrice); bool badExitLow = (ChExitLow[0] < HalfPrice); bool badExitHigh = (ChExitHigh[0] < HalfPrice); bool badFailHigh = (ChFailHigh[0] < HalfPrice); bool badFailLow = (ChFailLow[0] < HalfPrice); bool badStopDist = (StopMult * N[0] >= HalfPrice);
if(badEntryHigh || badEntryLow || badExitLow || badExitHigh || badFailHigh || badFailLow) printf("\n!!! %s bar %i: channel level below half the asset price %.5f (EntryHigh %.5f, EntryLow %.5f, ExitLow %.5f, ExitHigh %.5f, FailHigh %.5f, FailLow %.5f) -- Zorro reads such a value as a DISTANCE, not a level (stop.htm).", Asset, (int)Bar, (var)HalfPrice, (var)ChEntryHigh[0], (var)ChEntryLow[0], (var)ChExitLow[0], (var)ChExitHigh[0], (var)ChFailHigh[0], (var)ChFailLow[0]); if(badStopDist) printf("\n!!! %s bar %i: 2N stop distance %.5f is at or above half the asset price %.5f -- Zorro would read it as a LEVEL, not a distance (stop.htm).", Asset, (int)Bar, (var)(StopMult * N[0]), (var)HalfPrice); // [R-32] Exit levels are NOT gated -- suppressing an exit removes protection. if(badExitLow || badExitHigh) printf("\n@XLV,%s,%i,%.8f,%.8f,%.8f", Asset, (int)Bar, (var)ChExitLow[0], (var)ChExitHigh[0], (var)HalfPrice);
// ---- One-bar order-placement lag -------------------------- [R-16] // [R-16] Convention: every TEST reads [1], every ORDER is placed with [0]. var RestEntryHigh = ChEntryHigh[1]; var RestEntryLow = ChEntryLow[1]; var RestExitLow = ChExitLow[1]; var RestExitHigh = ChExitHigh[1]; var RestFailHigh = ChFailHigh[1]; var RestFailLow = ChFailLow[1]; var RestN = N[1];
// [R-08] Entry breaks are STRICT: the offset is in the test and in the // order, so shadow and real fill on the same bar at the same price. bool hitEntryHigh = (H[0] >= RestEntryHigh + BreakOffset); bool hitEntryLow = (L[0] <= RestEntryLow - BreakOffset); // [R-20] Exit stops are taken AT the level -- the break rule is on entries. bool hitExitLow = (L[0] <= RestExitLow); bool hitExitHigh = (H[0] >= RestExitHigh);
// ---- Shadow signal bookkeeping ---------- [R-22, R-28, R-21, R-33] int ScanK = scanIdx(Asset); // [R-33] int RealClosed = 0, Slot = -1, FillSlot = -1, OpenDir = 0; var RealExit = 0, Rested20 = 0; if(TrkID[0] != 0) { Slot = scanCls(ScanK, TrkID[0]); if(Slot >= 0) { RealClosed = 1; RealExit = ScanClsPx[ScanK*SCAN_W + Slot]; } } int ShStart = ShDir[0]; // [R-22] shadow state at bar start if(ShStart != 0 && TrkID[0] != 0) { // [R-33] A taken breakout closes with its real trade, never on the shadow tests. if(RealClosed) { classify(PrevLoss, HaveHist, ShStart, 3, (RealExit - ShEntry[0]) * ShStart); ShDir[0] = 0; } } else if(ShStart > 0) { // [R-28] 2N adverse excursion tested BEFORE the 10-day exit. if(L[0] <= ShAdv[0]) { classify(PrevLoss, HaveHist, 1, 1, ShAdv[0] - ShEntry[0]); ShDir[0] = 0; } else if(hitExitLow) { classify(PrevLoss, HaveHist, 1, 2, RestExitLow - ShEntry[0]); ShDir[0] = 0; } } else if(ShStart < 0) { if(H[0] >= ShAdv[0]) { classify(PrevLoss, HaveHist, -1, 1, ShEntry[0] - ShAdv[0]); ShDir[0] = 0; } else if(hitExitHigh) { classify(PrevLoss, HaveHist, -1, 2, ShEntry[0] - RestExitHigh); ShDir[0] = 0; } } if(RealClosed) TrkID[0] = 0; if(ShStart == 0) { // [R-21] Outside-bar tie-break: long tested first, deterministically. if(hitEntryHigh) OpenDir = 1; else if(hitEntryLow) OpenDir = -1; // [R-22] No same-bar close: a shadow opened here is tested from // the NEXT bar. } else if(ShDir[0] == 0) // [R-22] closed on this bar { // [R-22] An OPPOSITE break on the closing bar opens a new signal. if(ShStart > 0 && hitEntryLow) OpenDir = -1; else if(ShStart < 0 && hitEntryHigh) OpenDir = 1; } if(OpenDir != 0) { ShDir[0] = OpenDir; if(OpenDir > 0) ShEntry[0] = RestEntryHigh + BreakOffset; else ShEntry[0] = RestEntryLow - BreakOffset; ShAdv[0] = ShEntry[0] - OpenDir * StopMult * RestN; // [R-28] // [R-33] Taken: a same-direction fill this bar, from a 20-day order rested last bar. FillSlot = scanFill(ScanK, OpenDir); Rested20 = PlS[1]; if(OpenDir > 0) Rested20 = PlL[1]; if(FillSlot >= 0 && Rested20 == 1) { TrkID[0] = ScanFillID[ScanK*SCAN_W + FillSlot]; ShEntry[0] = ScanFillPx[ScanK*SCAN_W + FillSlot]; // [R-33] the real fill Slot = scanCls(ScanK, TrkID[0]); if(Slot >= 0) { // [R-33] The real trade also closed on its fill bar. classify(PrevLoss, HaveHist, OpenDir, 3, (ScanClsPx[ScanK*SCAN_W + Slot] - ShEntry[0]) * OpenDir); ShDir[0] = 0; TrkID[0] = 0; } } }
// ---- Previous-signal filter ------------------------ [R-22, R-23] // [R-22] Read AFTER this bar's shadow update. // [R-23] First signal on each asset is taken: there is no previous one. bool filterOK = (HaveHist[0] == 0) || (PrevLoss[0] > 0); FltBars += 1; if(filterOK) FltGreen += 1; // [R-22] census, trace only
// ---- Real orders ---- [R-14, R-18..R-21, R-27, R-29..R-32] if(NumOpenLong > 0) { // [R-19] Cancel the opposite pending order left alive by the fill. exitShort(0); // [R-20, R-30] Ratcheted 10-day channel exit, re-issued each bar at // the current level; it can only tighten. [R-27] the 2N stop stays // attached and the nearer of the two closes the trade. exitLong(0, ChExitLow[0]); } else if(NumOpenShort > 0) { exitLong(0); exitShort(0, ChExitHigh[0]); } else { // [R-18] Cancel yesterday's unfilled orders, then re-place fresh. // Reached ONLY when flat -- the branch structure IS the guard. exitLong(0); exitShort(0);
Stop = StopMult * N[0]; // [R-27] 2N hard stop, a DISTANCE to the fill price
// [R-29] Filter green: the 20-day levels. Filter red: the 55-day failsafe. var LongLevel = ChEntryHigh[0]; var ShortLevel = ChEntryLow[0]; bool badLong = badEntryHigh; bool badShort = badEntryLow; if(!filterOK) { LongLevel = ChFailHigh[0]; badLong = badFailHigh; ShortLevel = ChFailLow[0]; badShort = badFailLow; }
// [R-14] Family B: resting stop orders AT the level, not close tests. // [R-08] Entry carries the break offset. // [R-32] An order the engine would misread is suppressed, per side. if(badLong || badStopDist) printf("\n@SUP,%s,%i,L,%.8f,%.8f,%.8f", Asset, (int)Bar, (var)LongLevel, (var)HalfPrice, (var)(StopMult * N[0])); else { enterLong(1, LongLevel + BreakOffset); PlL[0] = filterOK; // [R-33] 1 = rested at the 20-day level }
if(badShort || badStopDist) printf("\n@SUP,%s,%i,S,%.8f,%.8f,%.8f", Asset, (int)Bar, (var)ShortLevel, (var)HalfPrice, (var)(StopMult * N[0])); else { enterShort(1, ShortLevel - BreakOffset); PlS[0] = filterOK; // [R-33] 1 = rested at the 20-day level } } } }
6
2,291
Read More
|
|
|
10/02/26 11:36
I tried setting History in z.ini but found it has not effect.
Would be great to have it working.
1
108
Read More
|
|
10/02/26 03:36
Hi, I'm reproducing Alice1 from the Black Book (EUR/USD, H1, 2016-2026, price history from the Zorro site, Zorro 3.11.2). With the original script I get roughly the book's result (PF around 1.4). On the chart, there is a gap of exactly 3 hourly bars after the weekend open: these 3 bars are missing and seem to be merged into the next bar, although every broker I checked shows them. I added BR_WEEKEND with StartWeek/EndWeek (and BarZone) to make those 3 bars reappear, so the bars match my broker (Darwinex/MT5). With otherwise the same logic, the result changes a lot: PF drops to about 1.1 with a much less regular equity curve. Removing only the weekend lines brings back the book's result. The effect seems even stronger on higher timeframes, for example H4, where the first bar after the weekend is clearly distorted without these settings. So my question: is this expected? Are those weekend bars skipped on purpose by default (to keep the example simple, or because those hours are illiquid), or am I doing something wrong in my setup? This is the script I used:
function run()
{
set(LOGFILE,PLOTNOW,PRELOAD);
Fill = 3;
Outlier = 0;
LookBack = 1000;
BarZone = 2; // match broker bars (Darwinex/MT5)
BarMode = BR_WEEKEND;
StartWeek = 10000; // Monday 00:00
EndWeek = 60000; // Saturday 00:00
StartDate = 20160101;
EndDate = 20260201;
MaxLong = MaxShort = 1;
vars Prices = series(price());
vars Trends = series(Laguerre(Prices,0.05));
vars MMI_Raws = series(MMI(Prices,500));
vars MMI_Avgs = series(Laguerre(MMI_Raws,0.05));
Stop = 10*ATR(500);
Lots = 1;
if(falling(MMI_Avgs)) {
if(valley(Trends))
enterLong();
else if(peak(Trends))
enterShort();
}
}
Asset EUR/USD and bar period 60 are selected in the Zorro window. Screenshot of the gap attached. Thanks!
1
127
Read More
|
|
|
10/02/26 01:31
That's good for me then with PayPal. I only asked about the source as the website appears a little dated and wanted to make sure that nothing had changed over the years. I'm currently using a Delphi API library and using C++ A7 SDK and now want to update to the A8 SDK. So, I need as much source code as possible.
One further question. How is the Pro SDK version delivered ? I do not have a Github or Discord account.
Many Thanks.
10
1,744
Read More
|
|
09/30/26 18:35
If you use the default TradeTest.c script as-is with Interactive Brokers, it will not work. Here's why. This line of code is the culprit: if(is(INITRUN)) brokerCommand(SET_ORDERTEXT,"TradeTest"); This of course looks like it would add a mere comment to a placed order. But that's not what happens with IB in particular. Instead, it sets the IB order's OrderType string value, which is a critical field. So if the order type is set to "TradeTest", the test order won't work. I expect that most newcomers to Zorro would not be able to figure this out without running the script in verbose mode and then debugging the script. Before I remove the line: !Open IB Socket 4.03 at UTC 09-30 17:39
ESZ6
ESZ6
Trade: TradeTest ESZ6 2026-09-30
Assets AssetsFutures
ESZ6
Buy Long ESZ6
!Order 4137 ES-FUT-ESZ6-ES-CME BUY TradeTest DAY 2 ES-FUT--0.00--CME/-ES-USD
!Error validating request.-'v' : cause - Invalid order type was entered ES-FUT--0.00--CME/-ES-USD
!Order rejected: error validating request.-'v' : cause - invalid order type was entered
Warning 075 (ESZ6::L) - can't open 2@7762 at 17:39:24
After I remove the line: !Open IB Socket 4.03 at UTC 09-30 17:39
ESZ6
ESZ6
Trade: TradeTest ESZ6 2026-09-30
Assets AssetsFutures
ESZ6
Buy Long ESZ6
!Order 4147 ES-FUT-ESZ6-ES-CME BUY MKT DAY 2 ES-FUT--0.00--CME/-ES-USD
[ESZ6::L04147] Long 2@7763.50 at 17:42:45
4147: Lots 2 Target 2 Open 7763.50000 Close 7763.50000
4147: Lots 2 Target 2 Open 7763.50000 Close 7763.75000
Note that "TradeTest" gets replaced with "MKT" (market order).
0
29
Read More
|
|
09/29/26 18:12
Small Update My starter reads the values from the engine starter like the progressbar etc and displays them on the loading screen. Even outside of lite-c acknex fights back...it is a witch work to get the percentage of the "8bit" old school starter window. it only works with Tricks (Width measurement) because Conitec used a custom class "class_WrProgress - the most efficient way possible".Now iam trying to do the same thing for the text, so i can directly read the start infos like cancel etc to react even more stable to engine start events. edit: I can really only chuckle at this point... everything in Acknex always puts up a fight XD ...even the measly starter text from the custom "class_wrTextF" can't be read out via message hook or RAM sniffing...crazy XD ...okay, so the only option left is "acklog sniffing." Thank god i can get the percentage from the starter... edit If "Diagnose" ist checked in the starter it shows the starter text on the loading info. I gave up on class_wrTextF and grab it from acklock.txt instead. edit Danger! I have rewritten the logic. my starter is now in control of the exec. i thought what happens if a faster pc want to go in fullscreen while the old engine just going out of fullscreen? Thats not good  ...so my starter shows the loadings screen, waits for the process to finish plus a few seconds and then starts the new engine. another edit: Ok it works now. But now im going back to do the exec from engine  ...but this time i simply switch in window mode before exit. Since i can feed and show a progress bar from engine starters progress i "hide" the starter window in window mode on swap via -nwnd (so its still in the task bar if user wants to see details. In "diagnose mode" it shows acklog text like i mentioned).
152
279,234
Read More
|
|
|
09/29/26 09:37
Only the source code of the included scripts, not of the engine. There are examples of using the SDK. The purchase link is for credit card payment, but you can order by email to Support if you want to pay with Paypal.
10
1,744
Read More
|
|
09/29/26 00:52
So i have implemented the "dirty hack"...i have to say...it looks good and works like a charm. (Engine swap means it reloads itself with other content/same content, not another acknex exe)Its done via a created file and intern exec. my own starter app checks for this file. if it does exist it shows a loading screen to hide the engine swap. i also made a security timer, if starter crashes, it removes the loading screen. if user press ESC or click the screen its removed (showing the engine start window if it still exists). So its "soft hidden" not "malware style" (while progging i locked my desktop XD ...good i had my second screen on). In window mode it just adds a loading info on top of the engine starter window while still showing it. The engine start window is modified to match the starter app's look. In fullscreen mode it fills the desktop in black color with a loading info label on top to hide the engines fullscreen switch. Before i exit the game i fade into a black screen, desktop is already black, new game loads in and fades the black screen out. If the starter detects an engine swap interruption, it asks the user whether they want to try reloading or not. The cool thing is, it reloads very quick. only the first start / loading of WRS takes a bit longer. This engine swap is almost invisible to the user and stable (as long as engine has read/write access on hd...and starter checks for this before starting the game). This way every click on new games "cleans" the memory so the game can run for ever And use a lot of content in theory...I use this starter since Dead Taste anyway, so it's another nice feature. Starter combines installation (downloading and/or installing of physicX etc), game and video settings and the game launch itself. A single START.exe with a sub folder (engine files WRS etc).
152
279,234
Read More
|
|
|
09/28/26 17:04
Well, I'm digging for more open wdl files. I'm hoping to become fluent enough in A3 WDL to make a youtube video about it. Firoball seems to have done some deep diving and preservation of the software but I dont know how to contact @fbl seems like he was last on the forums 5 years ago
50
30,144
Read More
|
|
|
09/28/26 10:17
What source code is included with the Pro A8 and are there any tutorials or guides on how to use the A8 SDK ?
10
1,744
Read More
|
|
09/27/26 20:38
Same here  the room is full of action figures (most of them vintage) in original package but only a few boxes.  But i can feel the urge of collectim them...i want a duke nukem big box, the first no atomic or something like that...200-300€! Nah... ![[Linked Image]](https://i.imgur.com/QMLV0SY.png) My HellCab is on ebay over two years now. Btw links to old a3 stuff would be cool yes.
50
30,144
Read More
|
|
09/27/26 20:12
I always wanted to know what was on the box! I have a few big boxes. Not a library or anything
50
30,144
Read More
|
|
09/27/26 19:23
Yes i love old games too and the boxes. i have a small collection in my game room with old pc bix box games. kingpin, ghostbusters II, willy beamish etc  And yes this package is indeed a beauty. I was a "kid" when i bought it. ![[Linked Image]](https://i.imgur.com/aWKCZrU.png) ![[Linked Image]](https://i.imgur.com/OtgFUYF.png) Conitec history.
50
30,144
Read More
|
|
|
09/27/26 18:47
That box is a thing of beauty!!! I do have the commercial release files. There was a long list of projects that were linked and re-linked above. They are dead links now. Thanks for indulging my necromancy with your reply. I love games and game tool preservation.
50
30,144
Read More
|
|
09/27/26 14:43
"Map entities" might work for you. A collection of entites / blocks in a WMB file loaded via ent_create (if you jiust want to "combine" static models but not moving) If not:
#define anm_frame skill80
var level_loading = 0;
action Actor_with_Gun_WED(){
while (my && level_loading) wait (1); // wait for level loading is done!
ENTITY* ent = ent_create("gun.mdl", vector(0,0,0), NULL); // create gun entity without action
//if (!ent){ safe_remove (me; return; }
while(my && !level_loading){
//if (!freeze_mode){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate(me, "walk", my.anm_frame, ANM_CYCLE);
if (ent){ // always check for valid pointers
//attach gun to "RightHand" bone
vec_for_bone(ent.x, my, "RightHand"); // move gun entity
//vec_for_vertex (ent.x, my, "123");
ang_for_bone(ent.pan, my, "RightHand"); // rotate entity
}
//}
wait(1);
}
//wait(1);//super safe XD
if (ent){
safe_remove (ent);
//ent = NULL; // global pointers only
}
safe_remove (me);
}
...
// safe level switch "no matter what"
level_loading = 1;
wait (-1);
level_load ("map2.wmb");
wait (5);
level_loading = 0;
...
"safe" global entity usage
ENTITY* ent_global_example;
action Blupp(){
// wait (1);
// set bbox etc
ent_global_example = me;
while (my && level_loading) wait (1);
while (my && !level_loading){
...
wait (1);
}
safe_remove (me);
ent_global_example = NULL;
}
action Bla(){
while (my && level_loading) wait (1);
//while (!ent_global_example) wait (1); // we check for it in the while anyway...
...
while (my && !level_loading){
if (ent_global_example){
...
}
wait (1);
}
safe_remove (me);
}
I try to use event_frame whenever possible (but with sub ents i would prefer while's too i have to say because with event_frame you might end up with XYZ/Pan,Tilt,Roll that are one frame to old!). Code below not tested but it should work:
#define anm_frame skill80
#define sub_ent_handle skill79
var level_loading = 0;
void event_testactor_wed(){
if (event_type == EVENT_FRAME && my.sub_ent_handle){
ENTITY* ent = ptr_for_handle (my.sub_ent_handle);
if (ent && !level_loading && !freeze_mode){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate (me, "idle", my.anm_frame, ANM_CYCLE);
vec_for_bone (ent.x, my, "RightHand");
ang_for_bone (ent.pan, my, "RightHand");
}
if (level_loading){
my.event = NULL;
if (ent) safe_remove (ent);
//ent = NULL; // global pointers
safe_remove (me);
//return; // if more event code below!
}
}
}
action TestActor_WED(){
while (my && level_loading) wait (1);
ENTITY* ent = ent_create ("gun.mdl", vector (0,0,0), NULL);
if (!ent){
safe_remove (me);
return;
}
else{
my.sub_ent_handle = handle (ent);
my.emask |= ENABLE_FRAME;
my.event = event_testactor_wed;
}
}
Or instead of ptr_for_handle its possible to use a global entity pointer, if the sub ent is only used by one entity. Another way, maybe more clean with more actors
#define anm_frame skill80
#define right_handed skill79
var level_loading = 0;
void attach_gun_to_actors (ENTITY* ent_actor, ent_gun){
if (!ent_actor || !ent_gun) return;
VECTOR tmp_pos;
ANGLE tmp_ang;
if (ent_actor.right_handed){
vec_for_bone (tmp_pos, ent_actor, "RightHand");
ang_for_bone (tmp_ang, ent_actor, "RightHand");
}
else{
vec_for_bone (tmp_pos, ent_actor, "LeftHand");
ang_for_bone (tmp_ang, ent_actor, "LeftHand");
}
vec_set (ent_gun.x, tmp_pos.x);
vec_set (ent_gun.pan, tmp_ang.pan);
}
/* The "skill1-line" is no comment instead WED will show "RightHanded" in object properties instead of "Skill1" (reload wmp or main script to show) ;)
Of course it makes no sense to use two skills for RightHanded...i just wanted to show this nice "hidden" WED feature here
That’s why I always go from high skill #defines down to low ones, so that the first skills can be used in WED. */
//skill1 RightHanded 1
action Actor_WED(){
while (my && level_loading) wait (1);
my.right_handed = my.skill1;
ENTITY* tmp_gun = ent_create ("gun.mdl", vector (0,0,0), NULL);
if (!tmp_gun){ safe_remove (me); return; }
while (my && !level_loading){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate (me, "idle", my.anm_frame, ANM_CYCLE);
attach_gun_to_actors (me, tmp_gun);
wait (1);
}
if (tmp_gun) safe_remove (tmp_gun);
safe_remove (me);
}
...
level_loading = 1;
wait (-1);
level_load ("map2.wmb");
wait (5);
level_loading = 0;
...
While the "level_loading" stuff may be optional at first, it makes things so much safer and easier later on, especially when it comes to interactions between multiple global pointers. Just wanted to say using stuff like "while(1)" with (global-) pointers can become dangerous very quick. I hope those example are "safe enough" for entity pointer usage and level switching. It's a good idea to set in your main function to keep constant! Btw...I prefer a struct with entities, very clean, easy and good for many sub ents.Greets
3
464
Read More
|
|
|
09/27/26 13:52
Publish shock (again...)
I found out the hard way that the known "memory leak" is much worse then i thought...(23:00 to 8:00 with AI)
Only the published version will crash (without error message or acklog-entry) if you play for at least 5 minutes and reloading the level 5-10 times! Edit: Note: if you play and respawn if you died, you can almost play for ever. It is the combination of "massive reloading" and "playing"! Never seen it crash without loading of any kind First of all i hate that the published version of every Acknex project acts different in 1000 ways to the sed start, but sadly thats not new (no matter what warn_level etc).
I tryed everything...i did manage to call level_load only once(thought level_load itself is the problem in combination with shadec), building the map by script manually (yes, terror), managed the nexus by hand via level_mark and level_free etc...still crashing. Nexus in this project atm 100-150mb max. So no "over 200" b*s*!
I guess the problem is deep in the shadec connection between Acknex and DirectX. Boh's "sc_reset" and "sc_destroy" functions just dont work(!) if you call them once after you called sc_setup.
It seams not possible to end shadeC evo if it started once...because its engine-pointers are "async" to GPU for one frame. I tryed to end it with new functions: it always ends in "invalid memory area" or "script crash in sc_forward_destroy / area_sc_reset ....". It seems to be a fundamental problem with the connection between Shadec and DirectX. I'm just guessing.
The only possible way to use shadeC with massive "world reloading" / level switch seams to use a extern process (like my starter app) to control level switch from outside of Acknex and hide the whole thing via a loading screen on the desktop. The only way i see to really clear the "corpses" from shadeC in the GPU: end engine - restart engine in new level/with new content. Without another process it could be done via exec and -nwnd option i guess... Anyway...its a ugly hack!
3run did modify shadec evo once, i dont know if he came to the same results. Would be interesting what he modified exactly in his shadec evo verson back then.
Maybe im wrong, but i say ShadeC evo needs to be rewritten from scratch to get rid of this "destroy" problem. I guess the mastermind Boh_Havoc did not test massive reloading/level switching in a published version. It seams like shadec was only tested like a techdemo in a single WMB with not much happening around it (will run forever). edit3: I was genuinely serious about "Mastermind"; I still take my hat off to the performance Boh_Havoc delivered here.
Just wanted to let you guys know.
edit2: Im pretty sure Dead Taste will show this behaviour too, when playing and clicking "new game" 5 times instead of clicking "Respawn" ...or how i called it back then.
If I'm talking nonsense here, I'm grateful to anyone who corrects me.
152
279,234
Read More
|
|
09/27/26 13:37
I still have the original A3 commercial version. I could offer the projects from the demo disk, if I can find the disks. "Skaphander" comes to mind right away, i think that was the name. Ah, those were the days....
50
30,144
Read More
|
|
|