rblood.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. function Player::reddenLimb(%player, %limb, %damage, %emphasis)
  2. {
  3. //!rBloodPlayerShapeAllowed(%player.getDataBlock().shapeFile)
  4. if(!$Pref::RBloodMod::LimbReddening || !rBloodPlayerShapeAllowed(%player.getDataBlock().shapeFile))
  5. return;
  6. if(%emphasis $= "")
  7. %emphasis = 0;
  8. %emphasis += $Pref::RBloodMod::LimbReddeningFactor;
  9. // switch chest string to one specifically meant for redding and not dismemberment
  10. if(%limb == 1)
  11. %limb = 6;
  12. // find out how much reddening we will do based on damage
  13. %damageMax = %player.getDatablock().maxDamage * getWord(%player.scale, 2);
  14. %damage = mCeil((mClampF(%damage, 0, %damageMax) / %damageMax) * 5);
  15. //%emphasis = mClamp(mCeil((%damageMax - %damage) / 40), 1, 100);
  16. for(%i = 0; %i < getWordCount($RBloodLimbString[%limb]); %i++)
  17. {
  18. %limbName = getWord($RBloodLimbString[%limb], %i);
  19. // incrementally blend the color
  20. %newColor = %player.nodeColor[%limbName];
  21. for(%b = 0; %b < %damage; %b++)
  22. {
  23. //%newColor = calcAdditiveRGB(%newColor, "0.4 0 0 1");
  24. if(%emphasis == 0)
  25. %newColor = calcAdditiveRGB(%newColor, "0.4 0 0 1");
  26. else
  27. %newColor = calcAdditiveRGB_emphasis(%newColor, "0.4 0 0 1", %emphasis);
  28. }
  29. // set new color
  30. %player.setNodeColor(%limbName, %newColor);
  31. %player.RBlood_NodeOverrideColor[%limbName] = %newColor;
  32. }
  33. }
  34. function Player::causeBleeding(%player, %duration, %bloodOverDuration, %startTime, %spread)
  35. {
  36. cancel(%player.rBloodBleedSchedule);
  37. %elapsed = (getSimTime() - %startTime);
  38. %stepTime = mClamp(%duration / %bloodOverDuration, 33, %duration);
  39. if(%spread > 0)
  40. %vector = vectorNormalize(vectorAdd("0 0 -1", ((getRandom() - 0.5) * %spread) SPC ((getRandom() - 0.5) * %spread) SPC ((getRandom() - 0.5) * %spread)));
  41. else
  42. %vector = "0 0 -1";
  43. doBloodSplatter(%vector, %player.getHackPosition(), 50);
  44. if(%elapsed > %duration)
  45. return;
  46. %player.rBloodBleedSchedule = %player.schedule(%stepTime, causeBleeding, %duration, %bloodOverDuration, %startTime, %spread);
  47. }
  48. function rbloodSplashNearbyPlayers(%position, %radius, %source, %intensity)
  49. {
  50. %mask = $TypeMasks::PlayerObjectType;
  51. initContainerRadiusSearch(%position, %radius, %mask);
  52. while(%player = containerSearchNext())
  53. {
  54. //if(%player == %source)
  55. // continue;
  56. %distance = mCeil(vectorDist(%player.getHackPosition(), %position));
  57. %iter = getRandom(3, 5);
  58. if(%intensity !$= "")
  59. %iter *= %intensity;
  60. if(%player == %source)
  61. %iter *= 0.75;
  62. %iter *= $Pref::RBloodMod::LimbReddeningSplash;
  63. for(%i = 0; %i < %iter; %i++)
  64. {
  65. %player.reddenLimb(getRandom(0, 5), 1, %distance);
  66. }
  67. }
  68. }
  69. // functions for spawning blood effects
  70. function doBloodExplosion(%position, %scale)
  71. {
  72. %bloodExplosionProjectile = new Projectile()
  73. {
  74. datablock = bloodBurstFinalExplosionProjectile;
  75. initialPosition = %position;
  76. };
  77. MissionCleanup.add(%bloodExplosionProjectile);
  78. %bloodExplosionProjectile.setScale(%scale SPC %scale SPC %scale);
  79. %bloodExplosionProjectile.explode();
  80. }
  81. function doBloodDismemberExplosion(%position, %scale)
  82. {
  83. %bloodDismemberProjectile = new Projectile()
  84. {
  85. datablock = bloodDismemberProjectile;
  86. initialPosition = %position;
  87. };
  88. MissionCleanup.add(%bloodDismemberProjectile);
  89. %bloodDismemberProjectile.setScale(%scale SPC %scale SPC %scale);
  90. %bloodDismemberProjectile.explode();
  91. }
  92. function doGibLimbsExplosion(%position, %scale)
  93. {
  94. for(%i = 0; %i < 3; %i++)
  95. {
  96. %datablock = $RBloodGib[%i];
  97. %bloodGibLimbsProjectile = new Projectile()
  98. {
  99. datablock = %datablock;
  100. initialPosition = %position;
  101. };
  102. MissionCleanup.add(%bloodGibLimbsProjectile);
  103. %bloodGibLimbsProjectile.setScale(%scale SPC %scale SPC %scale);
  104. %bloodGibLimbsProjectile.explode();
  105. }
  106. }
  107. // function for creating static-shape blood splatters that stick to surfaces
  108. // these arguments are hot garbage lmao. Sorry in advance to anyone who wants to use this
  109. function doBloodSplatter(%velocity, %position, %damage, %dataBlock)
  110. {
  111. if($Pref::RBloodMod::DisableStatic)
  112. return;
  113. if(%dataBlock !$= "")
  114. {
  115. %lifetime = %dataBlock.lifetime;
  116. if(%lifetime < 50)
  117. {
  118. %range = ((getRandom() - 0.5) * 6);
  119. }
  120. else
  121. {
  122. %range = 10 * (%lifetime / 125);
  123. }
  124. }
  125. else
  126. {
  127. %range = getRandom(8, 14);
  128. }
  129. %spread = %range;
  130. %projectileVector = vectorScale(vectorNormalize(%velocity), %range);
  131. %projectileVector = vectorAdd(%projectileVector, ((getRandom() - 0.5) * %spread) SPC ((getRandom() - 0.5) * %spread) SPC ((getRandom() - 0.5) * %spread));
  132. %start = %position;
  133. %end = vectorAdd(%position, %projectileVector);
  134. %mask = $TypeMasks::FxBrickObjectType | $TypeMasks::TerrainObjectType;
  135. %raycast = containerRayCast(%start, %end, %mask);
  136. %hit = getWord(%raycast, 0);
  137. //drawLine(%start, %end, "1 1 0 0.5", 0.2);
  138. if(isObject(%hit))
  139. {
  140. %end = getWords(%raycast, 1, 3);
  141. %normal = getWords(%raycast, 4, 6);
  142. %rotation = Normal2Rotation(%normal);
  143. %doStatic = true;
  144. }
  145. else
  146. {
  147. // hit nothing, simulate blood going to the floor
  148. %start = %end;
  149. %end = setWord(%start, 2, getWord(%start, 2) - 50);
  150. %raycast = containerRayCast(%start, %end, %mask);
  151. %hit = getWord(%raycast, 0);
  152. if(isObject(%hit))
  153. {
  154. %end = getWords(%raycast, 1, 3);
  155. %normal = getWords(%raycast, 4, 6);
  156. %rotation = Normal2Rotation(%normal);
  157. %doStatic = true;
  158. }
  159. }
  160. if(%doStatic)
  161. {
  162. %bloodPuddle = new StaticShape()
  163. {
  164. datablock = $RBloodPuddleStatic[getRandom(0, 1)];
  165. position = %end;
  166. rotation = %rotation;
  167. normal = %normal;
  168. };
  169. MissionCleanup.add(%bloodPuddle);
  170. %bloodPuddle.setNodeColor("ALL", $Pref::RBloodMod::BloodColor);
  171. %lifetime = $Pref::RBloodMod::BloodFadeTime;
  172. %bloodPuddle.schedule(%lifetime, delete);
  173. %bloodPuddle.bloodFadeLoop(%lifetime, 50, $Pref::RBloodMod::BloodColor);
  174. %scale = (mCeil(%damage / 64) + (2 * getRandom())) / 2;
  175. %bloodPuddle.setScale(%scale SPC %scale SPC %scale);
  176. if(!$Pref::RBloodMod::DisablePuddleTrigger)
  177. createBloodPuddleTrigger(%end);
  178. %downwardAngle = mRadtoDeg(mACos(vectorDot(%normal, "0 0 -1")));
  179. if(%downwardAngle < 80)
  180. {
  181. %bloodPuddle.doDripRBlood();
  182. }
  183. }
  184. }
  185. function createBloodPuddleTrigger(%position)
  186. {
  187. %trigger = new Trigger()
  188. {
  189. datablock = rbloodPuddleTriggerData;
  190. position = %position;
  191. polyhedron = "-0.5 -0.5 -0.5 1 0 0 0 1 0 0 0 1";
  192. creationTime = getSimTime();
  193. };
  194. %trigger.schedule($Pref::RBloodMod::BloodFadeTime * 0.75, delete);
  195. %trigger.setScale(0.5 SPC 0.5 SPC 0.2);
  196. return;
  197. }
  198. function rbloodPuddleTriggerData::onEnterTrigger(%data, %trigger, %player)
  199. {
  200. if(!rBloodPlayerShapeAllowed(%player.getDataBlock().shapeFile))
  201. return;
  202. %timeDif = getSimTime() - %trigger.creationTime;
  203. if(%timeDif < 1000)
  204. return;
  205. if(!%trigger.triggered)
  206. {
  207. %trigger.triggered = true;
  208. %player.reddenLimb(getRandom(4, 5), 1, 5);
  209. }
  210. return;
  211. }
  212. // function for fading a static shape out to invisibility over a certain period of time and increments
  213. function StaticShape::bloodFadeLoop(%shape, %lifetime, %increments, %color)
  214. {
  215. cancel(%shape.fadeLoopSchedule);
  216. %loopTime = %lifetime / %increments;
  217. %RGB = getWords(%color, 0, 2);
  218. %alpha = getWord(%color, 3);
  219. %alpha = %alpha - (getWord($Pref::RBloodMod::BloodColor, 3) / %increments);
  220. %newColor = %RGB SPC %alpha;
  221. %shape.setNodeColor("ALL", %newColor);
  222. %shape.fadeAlpha = %alpha;
  223. %shape.fadeLoopSchedule = %shape.schedule(%loopTime, bloodFadeLoop, %lifetime, %increments, %newColor);
  224. }
  225. function StaticShape::doDripRBlood(%shape)
  226. {
  227. cancel(%shape.rbloodDripLoop);
  228. %scale = mClampF(%shape.fadeAlpha, 0, 0.8);
  229. %vector = vectorNormalize(%shape.normal);
  230. %position = %shape.getPosition();
  231. %end = vectorAdd(%position, vectorScale(%vector, 0.25));
  232. //drawLine(%position, %end, "1 0 0 0.2", 0.2);
  233. %bloodDripProjectile = new Projectile()
  234. {
  235. datablock = rbloodDripProjectile;
  236. initialPosition = %end;
  237. initialVelocity = "0 0 -1";
  238. fadeAlpha = %shape.fadeAlpha;
  239. };
  240. MissionCleanup.add(%bloodDripProjectile);
  241. %bloodDripProjectile.setScale(%scale SPC %scale SPC %scale);
  242. %shape.rbloodDripLoop = %shape.schedule(getRandom(33, 2000), doDripRBlood);
  243. }
  244. function Player::RBloodSimulate(%obj, %position, %velocity, %projectileData, %projectileScale, %dismemberOnKill, %damage) {
  245. %data = %obj.getDatablock();
  246. //%damage = (%projectileData.directDamage * %projectileScale);
  247. %damage = %damage * 100 / %obj.getDatablock().maxDamage; // scale blood effects by HP %
  248. if(!rBloodPlayerShapeAllowed(%data.shapeFile))
  249. return;
  250. %obj.lastRBloodSimTime = getSimTime();
  251. // Some information about who we just shot
  252. %maxHP = %data.maxDamage;
  253. %currentHP = %maxHealth * (1 - %obj.getDamagePercent());
  254. %scale = getWord(%obj.getScale(), 2);
  255. %limb = %obj.rgetDamageLocation(%position);
  256. // Damage base blood effect
  257. %effectPosition = %position;
  258. %bloodAmount = mCeil(%damage / 16);
  259. %bloodAmountMax = 250;
  260. if(%bloodAmount>%bloodAmountMax) %bloodAmount = %bloodAmountMax;
  261. for(%i = 0; %i < %bloodAmount; %i++)
  262. {
  263. doBloodExplosion(%effectPosition, %scale);
  264. }
  265. schedule(0, 0, rbloodSplashNearbyPlayers, %effectPosition, 4, %obj, 0.6);
  266. serverPlay3D($RBlood::smallHit[getRandom(0, 3)], %effectPosition);
  267. // Blood splatters (static)
  268. for(%i = 0; %i < getRandom(2, 6); %i++)
  269. {
  270. doBloodSplatter(%velocity, %position, %damage, %projectileData);
  271. }
  272. // Hencefourth blood splattering caused by bleeding
  273. if(!$Pref::RBloodMod::DisableBleed)
  274. {
  275. %bloodTime = mCeil((%damage * 100) * $Pref::RBloodMod::BloodTimeScale);
  276. %bleedAmount = mCeil((%damage / 2) * $Pref::RBloodMod::BloodAmountScale);
  277. %obj.causeBleeding(%bloodTime, %bleedAmount, getSimTime());
  278. }
  279. // Node reddining on damage
  280. if($Pref::RBloodMod::LimbReddening)
  281. {
  282. %obj.reddenLimb(%limb, %damage);
  283. }
  284. // Dismemberment
  285. // Occurs only with high-powered weapons, like shotguns and 1-shot weapons
  286. // Dismemberment can only occur after death, so we store the limbs that are
  287. // marked for dismemberment, and then check the values at death for a valid
  288. // dismemberment condition.
  289. %obj.limbShotgunStrike = (getSimTime() - %obj.lastLimbHitTime[%limb] < 5); // if the limb was hit more than once within 5ms, we can assume we were shot by a shotgun
  290. %obj.lastLimbHitTime[%limb] = getSimTime();
  291. %obj.lastLimbDamage[%limb] = %damage;
  292. %obj.lastLimbDamagePosition[%limb] = %effectPosition;
  293. if(%damage > %maxHP || %obj.limbShotgunStrike || %damage >= $Pref::RBloodMod::DismemberDamage || %dismemberOnKill)
  294. {
  295. %obj.markLimbForDismember[%limb] = true;
  296. for(%i = 0; %i < getRandom(2, 6); %i++)
  297. {
  298. doBloodSplatter(%velocity, %position, %damage, %projectileData);
  299. }
  300. schedule(0, 0, rbloodSplashNearbyPlayers, %effectPosition, 6, %obj);
  301. }
  302. }
  303. package RBloodPackage
  304. {
  305. function Armor::Damage(%data, %obj, %sourceObject, %position, %damage, %damageType)
  306. {
  307. // Armor::Damage hook will provide functionality for weapons that do not use projectiles.
  308. // Due to the nature of Armor::Damage, this process is very tedious and ambiguous, and uses
  309. // a lot of hacky assumptive solutions.
  310. // First, determine whether or not RBlood was simulated already. if it has, there's no need to continue.
  311. %doRBloodSim = (getSimTime() - %obj.lastRBloodSimTime > 5);
  312. if(!%doRBloodSim)
  313. return Parent::Damage(%data, %obj, %sourceObject, %position, %damage, %damageType);
  314. if(%damage < $Pref::RBloodMod::MinimumBloodThreshold)
  315. return Parent::Damage(%data, %obj, %sourceObject, %position, %damage, %damageType);
  316. // We need to exclude certain damages that wouldn't make a lot of sense. You don't bleed in lava nor dor your limbs
  317. // explode when you commit suicide.
  318. if(%damageType == $DamageType::Lava || %damageType == $DamageType::Suicide)
  319. return Parent::Damage(%data, %obj, %sourceObject, %position, %damage, %damageType);
  320. %rbloodPosition = %position;
  321. %scale = getWord(%obj.scale, 2);
  322. %hs = 1;
  323. %vs = 2;
  324. %randomString = ((getRandom() - 0.5) * %hs * %scale) SPC ((getRandom() - 0.5) * %hs * %scale) SPC ((getRandom() - 0.5) * %vs * %scale);
  325. // Add-on makers don't always put in accurate information for %position. Sometimes this is done on purpose. Either way, we need to account for it.
  326. if(%rbloodPosition $= "" || %rbloodPosition $= "0 0 0" || vectorDist(%rbloodPosition, %obj.getHackPosition()) > (1.5 * %scale))
  327. {
  328. // bogus position. try to comp
  329. // Will get the center of the player and then randomly offset
  330. %rbloodPosition = %obj.getHackPosition();
  331. %rbloodPosition = vectorAdd(%rbloodPosition, %randomString);
  332. }
  333. // No projectile = no vector. We have no idea where the damage came from, so just bleed in the general downwards direction.
  334. %vector = vectorNormalize(vectorAdd("0 0 0", %randomString));
  335. // Dismembering.
  336. %dismember = (%damage >= $Pref::RBloodMod::DismemberDamage);
  337. %damage_old = %obj.getDamageLevel();
  338. Parent::Damage(%data, %obj, %sourceObject, %position, %damage, %damageType);
  339. %damage_new = %obj.getDamageLevel();
  340. if(%damage_new > %damage_old) {
  341. if(%damage_new < %data.maxDamage) %damage = %damage_new - %damage_old;
  342. %obj.schedule(0, RBloodSimulateArmor, %rbloodPosition, %vector, swordProjectile, 1, %dismember, %damage);
  343. }
  344. }
  345. function Player::RBloodSimulateArmor(%obj, %pos, %vec, %proj, %scl, %dis, %dmg) {
  346. if(getSimTime() - %obj.lastRBloodSimTime < 5) return;
  347. %obj.RBloodSimulate(%pos, %vec, %proj, %scl, %dis, %dmg);
  348. }
  349. function ProjectileData::Damage(%this, %projectile, %obj, %fade, %position, %normal)
  350. {
  351. %damage = (%this.directDamage * %projectile.scale);
  352. // avoid blood on damageless weapons like pushbrooms
  353. if(%damage < $Pref::RBloodMod::MinimumBloodThreshold)
  354. return Parent::Damage(%this, %projectile, %obj, %fade, %position, %normal);
  355. // functionality for developers who want to disable gore on their weapons
  356. if(%this.disableGore)
  357. return Parent::Damage(%this, %projectile, %obj, %fade, %position, %normal);
  358. if(%obj.getClassName()!$="Player" && %obj.getClassName()!$="AIPlayer")
  359. return Parent::Damage(%this, %projectile, %obj, %fade, %position, %normal);
  360. %damage_old = %obj.getDamageLevel();
  361. Parent::Damage(%this, %projectile, %obj, %fade, %position, %normal);
  362. %damage_new = %obj.getDamageLevel();
  363. if(%damage_new > %damage_old) {
  364. if(%damage_new < %data.maxDamage) %damage = %damage_new - %damage_old;
  365. %obj.RBloodSimulate(%position, %projectile.getVelocity(), %this, %projectile.scale, %this.dismemberOnKill, %damage);
  366. }
  367. }
  368. function Armor::onDisabled(%this, %obj, %state)
  369. {
  370. %position = %obj.getHackPosition();
  371. // check each limb for a dismemberment flag
  372. for(%limb = 0; %limb <= 5; %limb++)
  373. {
  374. %time = (getSimTime() - %obj.lastLimbHitTime[%limb]) < $Pref::RBloodMod::DismemberTime;
  375. %dism = %obj.markLimbForDismember[%limb];
  376. %dama = %obj.lastLimbDamage[%limb];
  377. %effectPosition = %obj.lastLimbDamagePosition[%limb];
  378. if(%time && %dism)
  379. {
  380. for(%i = 0; %i < getWordCount($RBloodLimbString[%limb]); %i++)
  381. {
  382. %obj.hideNode(getWord($RBloodLimbString[%limb], %i));
  383. }
  384. doBloodDismemberExplosion(%position, 1);
  385. if(!%obj.markForGibExplosion && isObject($RBlood_Stump[%limb]) && $Pref::RBloodMod::UseLimbStubs)
  386. %obj.mountimage($RBlood_Stump[%limb], 2);
  387. serverPlay3D($RBlood::HeavyHit[getRandom(0, 3)], %effectPosition);
  388. }
  389. }
  390. // were we in the middle of an explosion when we were killed? assume we were killed in an explosion and gib us
  391. if(%obj.markForGibExplosion)
  392. {
  393. %time = (getSimTime() - %obj.markForGibExplosionTime < 5);
  394. if(%time)
  395. {
  396. // hide everything and mount a ribcage to our chest, giving the illusion that it's part of the player model
  397. %obj.hideNode("ALL");
  398. %obj.setNodeColor("ALL", "0.4 0 0 1");
  399. %obj.mountimage(RBloodRibcageImage, 2);
  400. %obj.unMountImage(0);
  401. for(%i = 0; %i < getRandom(2, 3); %i++)
  402. {
  403. doBloodDismemberExplosion(%position, 1.5);
  404. doBloodExplosion(%position, 2);
  405. }
  406. %splatterAMT = getRandom(8, 16);
  407. %splatterAMT *= $Pref::RBloodMod::StaticBloodAmt;
  408. for(%i = 0; %i < %splatterAMT; %i++)
  409. {
  410. %vector = (getRandom() - 0.5) * 2 SPC (getRandom() - 0.5) * 2 SPC (getRandom() - 0.5) * 2;
  411. doBloodSplatter(%vector, %position, 100);
  412. }
  413. schedule(0, 0, rbloodSplashNearbyPlayers, %position, 10, %obj, 5);
  414. doGibLimbsExplosion(%position, getWord(%obj.scale, 2));
  415. }
  416. }
  417. Parent::onDisabled(%this, %obj, %state);
  418. }
  419. function ProjectileData::radiusDamage(%this, %obj, %col, %distanceFactor, %pos, %damageAmt)
  420. {
  421. %damage = %damageAmt * mClampF(%distanceFactor, 0, 1);
  422. if(!rBloodPlayerShapeAllowed(%col.getdataBlock().shapeFile) || %damage < $Pref::RBloodMod::MinimumBloodThreshold || %this.disableGore)
  423. return Parent::radiusDamage(%this, %obj, %col, %distanceFactor, %pos, %damageAmt);
  424. %hackPosition = %col.getHackPosition();
  425. %bloodAmount = mCeil(%damage / 24);
  426. for(%i = 0; %i < %bloodAmount; %i++)
  427. {
  428. doBloodExplosion(%hackPosition, 1);
  429. }
  430. schedule(0, 0, rbloodSplashNearbyPlayers, %hackPosition, 4, %col);
  431. if(!$Pref::RBloodMod::DisableBleed)
  432. {
  433. %bloodTime = mCeil((%damage * 50) * $Pref::RBloodMod::BloodTimeScale);
  434. %bleedAmount = mCeil((%damage / 2) * $Pref::RBloodMod::BloodAmountScale);
  435. %col.causeBleeding(%bloodTime, %bleedAmount, getSimTime());
  436. }
  437. if(%damageAmt < $Pref::RBloodMod::MinimumGibDamage)
  438. return Parent::radiusDamage(%this, %obj, %col, %distanceFactor, %pos, %damageAmt);
  439. %hackDistance = vectorDist(%pos, %hackPosition);
  440. if((%hackDistance / getWord(%col.scale, 2)) < $Pref::RBloodMod::DistanceToGib)
  441. {
  442. %col.markForGibExplosion = true;
  443. %col.markForGibExplosionTime = getSimTime();
  444. }
  445. Parent::radiusDamage(%this, %obj, %col, %distanceFactor, %pos, %damageAmt);
  446. }
  447. function ShapeBase::setNodeColor(%obj, %node, %color)
  448. {
  449. Parent::setNodeColor(%obj, %node, %color);
  450. // silly work around for not having a legitimate way to get node colors
  451. //rBloodPlayerShapeAllowed(%shape)
  452. %shape = %obj.getDatablock().shapeFile;
  453. if(rBloodPlayerShapeAllowed(%shape))
  454. %obj.nodeColor[%node] = %color;
  455. }
  456. };
  457. activatePackage(RBloodPackage);