1 //**************************************************************************
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
25 //**************************************************************************
26 class LightningThinker : Actor;
30 float NextLightningFlash;
32 array!int LightningLightLevels;
33 array!ubyte LightningSectors;
37 //==========================================================================
41 //==========================================================================
43 // check if the level is a lightning level
44 Sky1Texture = Level.Sky1Texture;
45 Sky2Texture = Level.Sky2Texture;
47 LightningLightLevels.length = XLevel.Sectors.length;
48 LightningSectors.length = (XLevel.Sectors.length+7)/8;
49 NextLightningFlash = Random()*15.0+5.0; // don't flash at level start
53 //==========================================================================
57 //==========================================================================
58 override void Tick (float DeltaTime) {
60 if (!NextLightningFlash || LightningFlash) {
61 DoLightningFlash(DeltaTime);
63 NextLightningFlash -= DeltaTime;
64 if (NextLightningFlash < 0.0) NextLightningFlash = 0.0;
65 if (bStopping) Destroy();
70 //==========================================================================
74 //==========================================================================
75 void DoLightningFlash (float DeltaTime) {
81 LightningFlash -= DeltaTime;
82 if (LightningFlash > 0.0) {
83 foreach (auto i; 0..XLevel.Sectors.length) {
84 tempSec = cast([unsafe])(&XLevel.Sectors[i]);
85 if (LightningSectors[i/8]&(1<<(i&7))) {
86 if (LightningLightLevels[i] < tempSec->params.lightlevel-4) {
87 tempSec->params.lightlevel -= 4;
92 // remove the alternate lightning flash special
94 foreach (auto i; 0..XLevel.Sectors.length) {
95 tempSec = cast([unsafe])(&XLevel.Sectors[i]);
96 if (LightningSectors[i/8]&(1<<(i&7))) {
97 tempSec->params.lightlevel = LightningLightLevels[i];
100 Level.Sky1Texture = Sky1Texture;
105 LightningFlash = Random()*0.25+0.25;
106 flashLight = 200+(P_Random()&31);
108 for (int i = (XLevel.Sectors.length+7)/8-1; i >= 0; --i) LightningSectors[i] = 0;
109 foreach (auto i; 0..XLevel.Sectors.length) {
110 tempSec = cast([unsafe])(&XLevel.Sectors[i]);
111 int Spec = tempSec->special&SECSPEC_BASE_MASK;
112 if (tempSec->ceiling.pic == Level.Game.skyflatnum ||
113 Spec == SECSPEC_LightningOutdoor ||
114 Spec == SECSPEC_LightningIndoor1 ||
115 Spec == SECSPEC_Lightningindoor2)
117 LightningLightLevels[i] = tempSec->params.lightlevel;
118 LightningSectors[i/8] |= 1<<(i&7);
119 if (tempSec->special == SECSPEC_LightningIndoor1) {
120 tempSec->params.lightlevel += 64;
121 if (tempSec->params.lightlevel > flashLight) {
122 tempSec->params.lightlevel = flashLight;
124 } else if (tempSec->special == SECSPEC_Lightningindoor2) {
125 tempSec->params.lightlevel += 32;
126 if (tempSec->params.lightlevel > flashLight) {
127 tempSec->params.lightlevel = flashLight;
130 tempSec->params.lightlevel = flashLight;
132 if (tempSec->params.lightlevel < LightningLightLevels[i]) {
133 tempSec->params.lightlevel = LightningLightLevels[i];
140 Level.Sky1Texture = Sky2Texture; // set alternate sky
141 PlaySound('world/thunder', CHAN_VOICE, 1.0, ATTN_NONE);
142 XLevel.StartTypedACScripts(VLevel::SCRIPT_Lightning, 0, 0, 0, Activator:none, Always:false, RunNow:false);
145 // calculate the next lighting flash
146 if (!NextLightningFlash) {
147 if (P_Random() < 50) {
148 // immediate quick flash
149 NextLightningFlash = (Random()*0.5)+0.5;
151 if (Random() < 0.5 && !(XLevel.TicTime&32)) {
152 NextLightningFlash = Random()*8.0+2.0;
154 NextLightningFlash = Random()*16.0+5.0;
161 //==========================================================================
165 //==========================================================================
166 void ForceLightning (int Mode) {
169 NextLightningFlash = 0.0;
176 NextLightningFlash = 0.0;