Advertisement
Guest User

Untitled

a guest
Nov 5th, 2021
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 63.98 KB | None | 0 0
  1. // --------------------------------------------------------
  2. // SAILING SCRIPT VERSION 1-39 BBK EDITION (modified for Opensim)
  3. // --------------------------------------------------------
  4. // BWind Sailing Engine Release 1-39-1
  5. // (sort of) by Becca Moulliez - RELEASE June 2010 - GNU/GPL
  6. // with many changes along the way, it seems
  7. // SAIL + APPARENT WIND
  8. // refer to boat name for release :
  9. // BOAT RELEASE-WIND ENGINE VERSION-LATEST UPDATE VERSION
  10. // i.e : 1-1-1
  11. // script based upon Kanker Greenacre's Flying Tako
  12. //------------------------------------------------------
  13. // Please do not remove this header
  14. // Permitted Free Uses
  15. // - allowed to use in your personal boats.
  16. // - allowed to use in boats you wish to sell or give away in second life.
  17. // - allowed to modify any part to your particular needs
  18. // Not Allowed Uses
  19. // - not allowed to re-package and give away, or sell this script.
  20. // - not allowed to change a few lines of code then call this your own work
  21. // - not allowed to take this to another platform or any use other than Second Life sailing without the express
  22. // permission from Becca Moulliez
  23. // ======= End Header =========
  24. //
  25. // All that being said above, how can we be GNU and restricted to SL at the same time? I don't think that works.
  26. // So since this is a substantial modification, the GNU fits. GPL for the win.
  27. //
  28. // Version 1-38-OS (Opensim) adds the following:
  29. //
  30. // 1) Spinnaker (was added somewhere in the journey to Opensim, I didn't do it, honest, I think it was Lotek's change)
  31. // 2) Spinnaker Pole (with the spinnaker)
  32. // 3) Fenders, hatch, tackle - for boats equipped with fenders or hatches or tackle that you want to either disappear or
  33. // appear depending on if you are sailing or not, there's support for this, name the fender prim "fender" and optionally the
  34. // face on the mesh prim. Likewise for hatch, also if the boom tackle is out, you can make that disappear too.
  35. //
  36. // 4) Ocean Engineering/WeatherOS wind setter to BWind (new commands setter/setoff) this takes real life wind
  37. // via the setter buoys, or any Ocean Engineering setter buoy for that matter, giving you "race mode" but maybe even
  38. // a little better even when not racing.
  39. //
  40. // 5) Windvane follows wind setting (stop using that stupid sim wind) - yes, a new windvane added. There is also a windvane script
  41. // you need to install in the windvane. The windvane will point into the direction bwind is set to, and will stay pointed at that direction.
  42. //
  43. // 6) tweaks for ubODE - mostly around the X-axis which seems determined to nose into the water on turns.
  44. // 7) disable motor when sails are up. That seemed like a bug.
  45. //
  46. // You can adapt this to any boat, if you wish. It would be nicer with mesh
  47. // sails, but the centres of the prims have to be on the edge to work right, you were warned. See the documentation.
  48. //
  49. // Version 1-39-OS (Opensim) adds the following new functions:
  50. //
  51. // 1) Implement course hold command. Type "hold" and the boat will follow the
  52. // current course/heading (in other words, the boat will stay pointed
  53. // in the direction you are heading, but that will also hold your course).
  54. // If you touch the wheel (left or right keys) it will disengage. So there is no "unhold" command for that reason.
  55. // 2) Some support for linked gauges is introduced here too. Specifically AWA is
  56. // now directly supported as well as a tachometer, the tach is rudimentary because
  57. // the engine is rudimentary.
  58. // 3) A number of bugs are fixed here. The most noticeable was the spinnaker appearing on sit, the startup and setup is complicated for
  59. // less than good reasons. quite a few other bugs in the hud, and other places.
  60. // 4) not directly part of this script, but spinnaker will shrink when not in use to prevent collisions, and the wake uses 1/2 the particles
  61. // and 2/3 the life to save on frame rate.
  62. // 5) Turn the tacking animation support on or off with a single flag. This saves commenting out code or remembering to.
  63. //
  64. // ----------------------------------------- START PROGRAMME ---
  65.  
  66. ///////////////////////////////////////////////////////////////////////
  67. // GLOBAL BOAT SETTINGS /////////////////////////////////////////////
  68. // you don't want to modify these settings unless specifically noted //////
  69. /////////////////////////////////////////////////////////////////////
  70.  
  71. //version settings
  72. string boatName="Sailboat 50D"; // Rename this according to your needs...
  73. string versionNumber="1-39-OS"; // Release reference
  74.  
  75. //script module flags
  76. integer CONTROLS_MODULE=1;
  77. integer SAIL_MODULE=2;
  78.  
  79. //environment
  80. vector wind;
  81. float windAngle;
  82. float absWindAngle;
  83. float seaLevel;
  84.  
  85. //reused math variables
  86. vector eulerRot;
  87. vector currEuler;
  88. rotation quatRot;
  89. rotation currRot;
  90.  
  91. //boat variables
  92. float zRotAngle;
  93. vector fwdVec;
  94. vector upVec;
  95. vector leftVec;
  96. float compass;
  97.  
  98. //heeling variables
  99. float heelAngle;
  100. float heelTorque;
  101. float heelAdd;
  102.  
  103. //linear motion variables
  104. float currSpeed;
  105. vector groundSpeed=ZERO_VECTOR;
  106. float spdFactor=0.0;
  107. float leeway;
  108.  
  109. //angular motion variables
  110. float rotSpeed;
  111. float rotDelta;
  112. vector eulerTurnLeft;
  113. vector eulerTurnRight;
  114. rotation quatTurnLeft=ZERO_ROTATION;
  115. rotation quatTurnRight=ZERO_ROTATION;
  116.  
  117. //sail variables
  118. integer sailingAngle;
  119. integer currBoomAngle=0;
  120. integer delta;
  121. integer incr;
  122. float optBoomAngle;
  123. float trimFactor;
  124.  
  125. //spinnaker variables
  126. integer spinAngle;
  127. integer spindelta;
  128. integer currSpinAngle=0;
  129. integer SPIN_UP=FALSE;
  130. integer CurJib;
  131. integer CurSpin;
  132. string Tack;
  133.  
  134. //performance constants - Standard defaults
  135.  
  136. float timerFreq=1.0; //timer frequency, seconds (original paramer 1.5; check this if gets laggy)
  137. integer sheetAngle=5; //initial sheet angle setting
  138. float maxWindSpeed=14.0; //used for heeling calculation (better leave this unchanged)
  139.  
  140. //miscellaneous settings
  141.  
  142. key owner; //boat owner
  143. key avatar; //avatar sitting at the helm
  144. integer lock=FALSE;
  145. integer ownerVersion=FALSE;
  146. integer SAIL_UP=FALSE;
  147. integer permSet=FALSE;
  148. integer HUD_ON=TRUE;
  149. string idStr;
  150. integer numTouches=0;
  151. integer sailing=TRUE;
  152. float mpsToKts=1.944; //Metres per Second to Knots conversion
  153. float convert=1.944;
  154. string units=" Kts.";
  155. integer showKnots=TRUE; //Yes we show speed in Knots...
  156. float time;
  157. float offset;
  158. float theta;
  159. integer msgTypeModeChange=40001;
  160. integer modeBWind=0;
  161. string helpString;
  162. string visualAid;
  163. vector hudcolour=<1,1,1>;
  164. string currentString;
  165. integer ADV_HUD=TRUE; //Advanced HUD off by default; set to TRUE to set on...
  166. integer useSetter=FALSE; // flag to use wind setter buoys
  167. integer courseHold=FALSE; // flag to indicate course hold is set
  168. float courseHoldValue; // the course to hold
  169. integer Tacking=FALSE; // does this boat use the tacking animations? Set to TRUE if so.
  170.  
  171.  
  172. //linked parts - childprims declarations; the rootscript will send commands to childs when running...
  173. //to work properly relevant prims MUST be renamed following the scheme below
  174.  
  175. integer JIB;
  176. integer SAIL;
  177. integer BOOM;
  178. integer HUD;
  179. integer CREWMAN; //this refers to the Crew Poseball in the cockpit...
  180. integer POLE; //NEW for Spinnaker
  181. integer SPINNAKER; //NEW for Spinnaker
  182. integer FENDERS; //if boat is equipped with fenders
  183. integer WINDVANE; //support windvane direction
  184. integer HATCHUPPER;
  185. integer HATCHLOWER; // for closing and opening the hatch
  186. integer L33; // boom tackle
  187. integer AWI1; // apparent wind gauge
  188. integer TACH; // tachometer
  189.  
  190.  
  191. //general sailing parameters
  192. float ironsAngle=31; //this is as close as the boat can sail to the wind
  193. float slowingFactor=0.7; //speed drops by this factor every timerFreq seconds if sailing into the wind
  194. float leewayTweak=1.50; //scales leeway (0=no leeway)
  195. float rotTweak=0.8; //scales boat turning rate
  196. float speedTweak=1.0; //DON'T touch this !!!!!!!!
  197.  
  198. //Apparent Wind parameters
  199. vector tmpwind;
  200. float truewindDir;
  201. float truewindSpeed;
  202. float truewindAngle;
  203. float appwindSpeed;
  204. float appwindAngle;
  205.  
  206.  
  207. // Buoy listener/setter globals
  208. //
  209. integer windh=-1; //handle for listening to scripted wind
  210. vector windvec=<0,1,0>; //default to north
  211.  
  212. // ------------------------- END GLOBAL BOAT SETTINGS ---
  213.  
  214. ///////////////////////////////////////////////////////
  215. // BWIND DEFAULT PRESET DECLARATION //////////////////
  216. // modify this section as per 15 Knots Wind Preset //
  217. ////////////////////////////////////////////////////
  218.  
  219. //The boat will sail a 15 Knots East BWind by default... following parameters apply
  220.  
  221. float windDir=0; //BWind Wind direction
  222. string windRose="East "; //BWind Preset declaration for 15 Knots Wind
  223. string windType="15 Knots"; //BWind Preset declaration for 15 Knots Wind
  224.  
  225. //primary parameters
  226. float windSpeed=7.75; // Don't touch this... 15 Knots Speed
  227. float maxSpeed=5.5; // Edit this according to your needs... this is the actual Speed with a 15 Knots Wind
  228. float heelTweak=0.85; // Edit this according to your needs... this is the actual Heel for a 15 Knots Wind
  229.  
  230. //Note : you MUST check the 15 Knots BWind Preset below in the Script (line 829); The values set here MUST be the same...
  231.  
  232. // --------------------------- END DEFAULT PRESET DECLARATION ---
  233.  
  234. ///////////////////////////////////////////////////
  235. // GLOBAL BOAT EQUATIONS AND FUNCTIONS ///////
  236. // you don't want to modify these settings //////
  237. ////////////////////////////////////////////////
  238.  
  239. //Following Equations and Functions will affect GLOBAL Boat's behavior -- I strongly recommend you will NOT edit unless you know what you are doing...
  240.  
  241.  
  242. // BWind Basic Boat Behaviour - LSL Angle Calculation
  243.  
  244. integer realAngle2LslAngle(integer realAngle) {
  245. integer lslAngle= (realAngle-90)*-1;
  246. while(lslAngle>=360) lslAngle-=360;
  247. while(lslAngle<0) lslAngle+=360;
  248. return lslAngle;
  249. }
  250.  
  251. // BWind Basic Boat Behaviour - calculate wind angle
  252.  
  253. //TRUE WIND - True Wind has been left as a separate routine in case you dont want your boat to support Apparent Wind
  254. calcTrueWindAngle() {
  255. currRot=llGetRot();
  256. currEuler=llRot2Euler(currRot);
  257. zRotAngle=currEuler.z;//boat heading
  258. leftVec=llRot2Left(currRot);
  259. truewindAngle=windDir-zRotAngle;
  260. while (truewindAngle>PI) truewindAngle-=TWO_PI; //bw -PI and PI
  261. while (truewindAngle<-PI) truewindAngle+=TWO_PI; //bw -PI and PI
  262. if ((truewindAngle) < 0) {
  263. truewindAngle = truewindAngle * -1;
  264. }
  265. }
  266.  
  267. //APPARENT WIND
  268. calcAppWindAngle() {
  269. currRot=llGetRot();
  270. currEuler=llRot2Euler(currRot);
  271. zRotAngle=currEuler.z; //boat heading
  272. leftVec=llRot2Left(currRot);
  273. windAngle=windDir-zRotAngle;
  274. while (windAngle>PI) windAngle-=TWO_PI; //bw -PI and PI
  275. while (windAngle<-PI) windAngle+=TWO_PI; //bw -PI and PI
  276. vector boatMovement=<currSpeed*llCos(currEuler.z),currSpeed*llSin(currEuler.z),0>;
  277. tmpwind=wind+boatMovement;
  278. float spd=llVecMag(llGetVel());
  279. appwindAngle=llAtan2(windSpeed*llSin(windAngle),(windSpeed*llCos(windAngle)+spd));
  280. while (appwindAngle>PI) spd=-spd;
  281. while (appwindAngle<-PI) spd=-spd;
  282. appwindSpeed=spd*llCos(llFabs(windAngle))-windSpeed*llCos(windAngle);
  283. if ((appwindSpeed) < 0) {
  284. appwindSpeed = appwindSpeed * -1;
  285. }
  286. if ((appwindSpeed) > 3) {
  287. appwindSpeed = appwindSpeed -(TWO_PI-1.0);
  288. }
  289. // in order for the AWA gauge to work properly it needs to know negative
  290. // deflection, therefore we don't want to use absolute value (all of this could
  291. // be simplified with llFabs() but whatever...
  292. // if ((appwindAngle) < 0) {
  293. // appwindAngle = appwindAngle * -1;
  294. // }
  295. }
  296.  
  297. // BWind Basic Boat Behaviour - calculate heel angle based on wind and sail settings
  298.  
  299. calcHeelAngle() {
  300. heelAngle=llAsin(leftVec.z);
  301. if (SAIL_UP) {
  302. if (llFabs(windAngle+sailingAngle)>3*DEG_TO_RAD) {
  303. heelTorque=SAIL_UP*llSin(windAngle)*llCos(heelAngle)*PI_BY_TWO*(windSpeed/maxWindSpeed)*llCos(sailingAngle*DEG_TO_RAD)*heelTweak;
  304. } else heelTorque=0;
  305. } else heelTorque=0;
  306. heelAdd=heelTorque-heelAngle;
  307. eulerRot=<heelAdd,0,0>;
  308. quatRot=llEuler2Rot(eulerRot);
  309. }
  310.  
  311. // BWind Basic Boat Behaviour - calculate angle of sail (or jib) based on sheet setting and the wind
  312.  
  313. calcBoomDelta() {
  314. if (sheetAngle<=0) sheetAngle=5; //never let the actual sheetangle be less than 5°
  315. if (sheetAngle>=79) sheetAngle=79; //never let the actual sheetangle be more than 79°
  316. sailingAngle=sheetAngle;
  317. if (sailingAngle>llFabs(windAngle*RAD_TO_DEG)) sailingAngle=llRound(llFabs(windAngle*RAD_TO_DEG));
  318. if (windAngle<0) sailingAngle*=-1;
  319. delta=sailingAngle-currBoomAngle;
  320. currBoomAngle=sailingAngle;
  321. if (currBoomAngle < 0) Tack="Starb'd";
  322. if (currBoomAngle > 0) Tack="Port";
  323. currBoomAngle=sailingAngle;
  324. llMessageLinked(SAIL,delta,"",NULL_KEY);//tell sail to rotate by delta
  325. llMessageLinked(JIB,delta,"",NULL_KEY);//tell jib to rotate by delta
  326. llMessageLinked(BOOM,delta,"",NULL_KEY);//tell boom to rotate by delta
  327. }
  328.  
  329. // BWind Basic Boat Behaviour - calculate boat speed
  330.  
  331. calcSpeed() {
  332. groundSpeed=llGetVel();
  333. absWindAngle=llFabs(windAngle);
  334. if (llFabs(absWindAngle*RAD_TO_DEG-llFabs(sailingAngle))<10) trimFactor=0;
  335. else {
  336. optBoomAngle=0.5*absWindAngle*RAD_TO_DEG;
  337. trimFactor=(90.-llFabs(optBoomAngle-llFabs(sailingAngle)))/90.;
  338. }
  339. //(old)if (absWindAngle<ironsAngle*DEG_TO_RAD) currSpeed*=slowingFactor;
  340. if (llFabs(appwindAngle)<ironsAngle*DEG_TO_RAD) currSpeed*=slowingFactor;
  341. else {
  342. if (SAIL_UP) {
  343. //currSpeed=speedTweak*(llCos(windAngle/2.)+0.5)*windSpeed*trimFactor;
  344. //if (currSpeed>maxSpeed) currSpeed=maxSpeed;
  345. currSpeed=speedTweak*(llSin(llFabs(windAngle)/2)+llCos(llFabs(windAngle)/2.75) - 0.75)*windSpeed*trimFactor; // mod donated by Eta Carver
  346. }
  347. else currSpeed*=0.8;
  348. }
  349. }
  350.  
  351. // BWind Basic Boat Behaviour - calculate leeway (lateral drift) due to wind
  352.  
  353. calcLeeway() {
  354. leeway=SAIL_UP*-llSin(llFabs(appwindAngle))*llSin(heelAngle)*windSpeed*leewayTweak;
  355. //BUG found by Balduin Aabye - ty :))
  356. }
  357.  
  358.  
  359. // BWind Basic Boat Behaviour - calculate turning rate based on current speed
  360. calcTurnRate() {
  361. spdFactor=llVecMag(groundSpeed)/(maxSpeed);
  362. rotSpeed=0.5+(spdFactor)/2.0;
  363. }
  364.  
  365. // String Conversions - automatically detect link nums for each named part - based upon original Tako parts names
  366.  
  367. getLinkNums() {
  368. integer i;
  369. integer linkcount=llGetNumberOfPrims();
  370. for (i=1;i<=linkcount;++i) {
  371. string str=llGetLinkName(i);
  372. if (str=="jib") JIB=i;
  373. if (str=="sail") SAIL=i;
  374. if (str=="boom") BOOM=i;
  375. if (str=="pole") POLE=i;
  376. if (str=="spinnaker") SPINNAKER=i;
  377. if (str=="hud") HUD=i;
  378. if (str=="crewman") CREWMAN=i;
  379. if (str=="fenders") FENDERS=i;
  380. if (str=="windvane") WINDVANE=i;
  381. if (str=="hatchupper") HATCHUPPER=i;
  382. if (str=="hatchlower") HATCHLOWER=i;
  383. if (str=="l33") L33 = i;
  384. if (str=="awi1") AWI1 = i;
  385. if (str=="tach") TACH = i;
  386.  
  387. }
  388. }
  389.  
  390.  
  391. fenders(float visible)
  392. {
  393. float openshut; // hatch does the opposite
  394.  
  395. if (visible > 0)
  396. {
  397. openshut = 0.0;
  398. }
  399. else
  400. {
  401. openshut = 1.0;
  402. }
  403.  
  404. llSetLinkAlpha(FENDERS,visible,ALL_SIDES);
  405. llSetLinkAlpha(L33,visible,ALL_SIDES);
  406. llSetLinkAlpha(HATCHUPPER,openshut,ALL_SIDES);
  407. // llSetLinkPrimitiveParamsFast(HATCHUPPER,[PRIM_PHANTOM,(integer)visible]);
  408. llSetLinkAlpha(HATCHLOWER,openshut,ALL_SIDES);
  409. // llSetLinkPrimitiveParamsFast(HATCHLOWER,[PRIM_PHANTOM,(integer)visible]);
  410. }
  411.  
  412. setAWI(float appAngle)
  413. {
  414. llMessageLinked(AWI1,22,(string)appAngle,"");
  415. }
  416.  
  417. setTach(float rpm)
  418. {
  419. llMessageLinked(TACH,-123202,(string)rpm,"");
  420. }
  421.  
  422. setWindvane(float wDir)
  423. {
  424. // given a direction, send it to the windvane, it'll point in that general direction and jiggle around a few degrees
  425. llMessageLinked(WINDVANE,0,(string)wDir,"");
  426. }
  427.  
  428. // use the WeatherOS/OE buoy
  429.  
  430. setWindFromBuoy()
  431. {
  432. windh = llListen(-54001,"","","");
  433. }
  434.  
  435.  
  436. // RAISE ROUTINE - raise sail: start timer
  437.  
  438. raiseSail() {
  439. SAIL_UP=TRUE;
  440. llOwnerSay("Ready to sail... ");
  441.  
  442. llMessageLinked(SAIL,1002,"",NULL_KEY); // raise sail
  443. llMessageLinked(JIB,1002,"",NULL_KEY); // raise jib
  444.  
  445.  
  446. llMessageLinked(SPINNAKER,1001,"",NULL_KEY); // don't raise spinnaker
  447.  
  448.  
  449. llMessageLinked(BOOM,1002,"",NULL_KEY); // move boom
  450. llMessageLinked(CREWMAN,1000,"",NULL_KEY); // hide crewman poseball
  451. fenders(0.0); // hide fenders, shut hatches
  452.  
  453. llSetTimerEvent(timerFreq);
  454. llLoopSound("sailing", 1.0);
  455.  
  456. }
  457.  
  458. // LOWER ROUTINE - lower sail but leave physics on
  459.  
  460. lowerSail() {
  461. llOwnerSay("Lowering sails... ");
  462. llMessageLinked(SAIL,1000,"",NULL_KEY);//lower sail w/ reset
  463. llMessageLinked(JIB,1000,"",NULL_KEY);//lower jib w/ reset
  464. llMessageLinked(BOOM,1000,"",NULL_KEY);//stop boom w/ reset
  465. llMessageLinked(POLE,1000,"",NULL_KEY);//stop pole w/ reset
  466. llMessageLinked(SPINNAKER,1000,"",NULL_KEY); // drop and reset spinnaker
  467. fenders(1.0); // put the fenders out, open the hatches
  468. sailingAngle = 0;
  469. llStopSound();
  470. llMessageLinked(LINK_ALL_CHILDREN , 0, "stop", NULL_KEY); // stop all children-linked activities
  471. currBoomAngle=0;
  472. sheetAngle=5;
  473. SAIL_UP=FALSE;
  474. llSetObjectDesc (""); //This sets your boat's description string when lowering... useful when you add a WWC Wind routine
  475. }
  476.  
  477. //SPINNAKER ROUTINE
  478. HoistSpin(){
  479. if ((sheetAngle > 50)) {
  480. llOwnerSay("Hoisting Spinnaker");
  481. llMessageLinked(SPINNAKER,1002,"",NULL_KEY); //hoist spinnaker
  482. if (-sailingAngle > 0) llMessageLinked(POLE,1002,"",NULL_KEY);
  483. if (-sailingAngle < 0) llMessageLinked(POLE,1004,"",NULL_KEY);
  484. llMessageLinked(JIB,1001,"",NULL_KEY); //lower jib
  485. SPIN_UP=TRUE;
  486. CurJib=0;
  487. }
  488. if ((sheetAngle < 50)) {
  489. llOwnerSay("Sheet too close to Hoist Spin");
  490. }
  491. }
  492. DropSpin(){
  493. llOwnerSay("Dropping Spinnaker");
  494. llMessageLinked(SPINNAKER,1000,"",NULL_KEY); //drop spinnaker/W reset
  495. llMessageLinked(POLE,1000,"",NULL_KEY); // hide & reset pole
  496. llMessageLinked(JIB,1002,"",NULL_KEY); //raise jib
  497. CurSpin=0;
  498. CurJib=0;
  499. currSpinAngle=0;
  500. spinAngle=0;
  501. SPIN_UP=FALSE;
  502. }
  503. TrimSpinPlus() {
  504. if (CurSpin < 37) {
  505. llMessageLinked(SPINNAKER,(delta+3),"",NULL_KEY); //trim spinnaker +
  506. llMessageLinked(POLE,(delta+3),"",NULL_KEY); // hide pole
  507. CurSpin=CurSpin+3;
  508. }
  509.  
  510. }
  511. TrimSpinMinus() {
  512. if (CurSpin > -37) {
  513. llMessageLinked(SPINNAKER,(delta-3),"",NULL_KEY); //trim spinnaker -
  514. llMessageLinked(POLE,(delta-3),"",NULL_KEY); // hide pole
  515. CurSpin=CurSpin-3;
  516. }
  517. }
  518.  
  519. // VEHICLE PHYSICS PARAMETERS - set initial vehicle parameters
  520.  
  521. // WARNING !!!! - Following physics parameters should NOT be edited unless you REALLY KNOW what you are doing....
  522.  
  523. setVehicleParams() {
  524. //vehicle flags
  525. llSetLinkPrimitiveParamsFast(LINK_ALL_CHILDREN, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]);
  526.  
  527. llSetVehicleType (VEHICLE_TYPE_BOAT);
  528. llSetVehicleRotationParam(VEHICLE_REFERENCE_FRAME,ZERO_ROTATION); // ZERO_ROTATION = <0.0,0.0,0.0,1.0> you may wish to edit this for fun
  529. llSetVehicleFlags (VEHICLE_FLAG_NO_DEFLECTION_UP|VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT|VEHICLE_FLAG_LIMIT_MOTOR_UP );
  530. //linear motion
  531. llSetVehicleVectorParam (VEHICLE_LINEAR_FRICTION_TIMESCALE,<20.0,2.0,0.5>);;
  532. llSetVehicleVectorParam (VEHICLE_LINEAR_MOTOR_DIRECTION,ZERO_VECTOR);
  533. llSetVehicleFloatParam (VEHICLE_LINEAR_MOTOR_TIMESCALE,5.0);
  534. llSetVehicleFloatParam (VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE,10);
  535. llSetVehicleFloatParam (VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,0.85);
  536. llSetVehicleFloatParam (VEHICLE_LINEAR_DEFLECTION_TIMESCALE,1.0);
  537. //angular motion
  538. llSetVehicleVectorParam (VEHICLE_ANGULAR_FRICTION_TIMESCALE,<5,0.1,0.1>);
  539. llSetVehicleVectorParam (VEHICLE_ANGULAR_MOTOR_DIRECTION,ZERO_VECTOR);
  540. llSetVehicleFloatParam (VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.1);
  541. llSetVehicleFloatParam (VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE,3);
  542. llSetVehicleFloatParam (VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY,1.0);
  543. llSetVehicleFloatParam (VEHICLE_ANGULAR_DEFLECTION_TIMESCALE,1.0);//default 1.0 -- reduce to have more lateral drift (like 0.3 - 0.5)
  544. //vertical attractor
  545. llSetVehicleFloatParam (VEHICLE_VERTICAL_ATTRACTION_TIMESCALE,3.0);
  546. llSetVehicleFloatParam (VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY,0.8);
  547. //banking
  548. llSetVehicleFloatParam (VEHICLE_BANKING_EFFICIENCY,0.0);
  549. llSetVehicleFloatParam (VEHICLE_BANKING_MIX,1.0);
  550. llSetVehicleFloatParam (VEHICLE_BANKING_TIMESCALE,1.2);
  551. //vertical control
  552. llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel);
  553. llSetVehicleFloatParam (VEHICLE_HOVER_EFFICIENCY,2.0);
  554. llSetVehicleFloatParam (VEHICLE_HOVER_TIMESCALE,1.0);
  555. llSetVehicleFloatParam (VEHICLE_BUOYANCY,1.0);
  556. }
  557.  
  558. //MASTMAN AND CREW CAMERA SETUP - set camera position for third person view
  559.  
  560. setCamera() {
  561. llSetCameraEyeOffset(<-11.5,0.0,4.7>); //Here you may set your Sailing Camera EYE Offset
  562. llSetCameraAtOffset(<3.0,0.0,1.0>); //Here you may set your Sailing Camera actual position
  563. }
  564.  
  565. //REZZING INITIAL POSITION - figure out where to put boat when it is rezzed
  566. // The boat will float at a 20.100 level... Edit and raise/lower the rootprim to set your waterline... DON'T mod THIS !
  567. setInitialPosition() {
  568. vector pos=llGetPos();
  569. float groundHeight=llGround(ZERO_VECTOR);
  570. float waterHeight = llWater(ZERO_VECTOR);
  571. seaLevel=llWater(ZERO_VECTOR);
  572. upright();
  573. //if over water, set boat height to sealevel + 0.1m; this is the standard default water level
  574. if (groundHeight <= waterHeight) {
  575. pos.z = waterHeight + 0.1; //fixed by Balduin Aabye (originally 0.12)
  576. while (llVecDist(llGetPos(),pos)>.001) llSetPos(pos);
  577. }
  578. }
  579.  
  580. //SIT TARGET - REFER TO pose_s SCRIPT FOR MASTMAN AND CREW SET - set sit target for helmsperson
  581. //this function is now being disabled - there is an external pose script to set this...
  582.  
  583. setSitTarget() {
  584. llSetSitText("Sail !");
  585. llSetText("",ZERO_VECTOR,1.0);
  586. }
  587.  
  588. //BOAT UPRIGHT POSITION - force boat upright
  589.  
  590. upright() {
  591. currRot=llGetRot();
  592. currEuler=llRot2Euler(currRot);
  593. leftVec=llRot2Left(currRot);
  594. heelAngle=llAsin(leftVec.z);
  595. eulerRot=<-heelAngle,0,0>;
  596. quatRot=llEuler2Rot(eulerRot);
  597. llRotLookAt(quatRot*currRot,0.2,0.2);
  598. }
  599.  
  600. //MOORING FUNCTION - what happens when your boat moors...
  601.  
  602. moor() {
  603. llMessageLinked(LINK_THIS,SAIL_MODULE,"moor",NULL_KEY);
  604. {
  605. llSetTimerEvent(timerFreq);
  606. sailing=TRUE;
  607. }
  608. llOwnerSay("Mooring.");
  609. upright();
  610. llReleaseControls();
  611. llSetStatus(STATUS_PHYSICS,TRUE);
  612. llSetTimerEvent(0);
  613. currSpeed=0;
  614. }
  615.  
  616. //GENERAL BOAT STARTUP - reset stuff - this resets the script to defaults... you may call this function as needed...
  617.  
  618. startup() {
  619. owner=llGetOwner();
  620. llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Z | STATUS_ROTATE_Y,TRUE);
  621. llSetStatus(STATUS_PHYSICS,FALSE);
  622. llSetStatus(STATUS_PHANTOM,FALSE);
  623. llSetStatus(STATUS_BLOCK_GRAB,TRUE);
  624. llSetTimerEvent(0);
  625. setInitialPosition();
  626. setVehicleParams();
  627. setSitTarget();
  628. getLinkNums();
  629. llMessageLinked(SAIL,1000,"",NULL_KEY); //reset MAINSAIL
  630. llMessageLinked(JIB,1000,"",NULL_KEY); //reset JIB
  631. llMessageLinked(BOOM,1000,"",NULL_KEY); //reset BOOM
  632. llMessageLinked(CREWMAN,1001,"",NULL_KEY); // show crewman poseball
  633. llMessageLinked(POLE,1000,"",NULL_KEY); // hide & reset pole
  634. llMessageLinked(SPINNAKER,1001,"",NULL_KEY); //reset SPINNAKER
  635. setCamera(); //apply Camera default setting
  636. currSpeed=0;
  637. llListen(0,"",owner,""); //listen to boat owner only...
  638. llOwnerSay("Ready.");
  639. llMessageLinked(LINK_ALL_CHILDREN , 0, "stop", NULL_KEY);
  640. }
  641.  
  642. updateCourse()
  643. {
  644. float compass=zRotAngle*RAD_TO_DEG;
  645. compass = (450.0 - compass)%360.0;
  646. //llOwnerSay("Compass "+(string)compass);
  647. //llOwnerSay("Hold at "+(string)courseHoldValue);
  648. //llOwnerSay("rotSpeed "+(string)rotSpeed);
  649.  
  650. float compDiff = compass - courseHoldValue;
  651.  
  652. if (llFabs(compDiff) > 350.00)
  653. {
  654. compass = compass + 360.00;
  655. }
  656.  
  657. if (compass > (courseHoldValue+1))
  658. {
  659. // need to turn left
  660. //llOwnerSay("left turn");
  661. //llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,1.0>);
  662. llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,rotSpeed/35.0>);
  663. }
  664. else
  665. {
  666. if (compass < (courseHoldValue-1))
  667. {
  668. //llOwnerSay("right turn");
  669. // need to turn right
  670. //llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,-1.0>);
  671. llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,-rotSpeed/35.0>);
  672. }
  673. }
  674. //llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,0.0>);
  675. }
  676.  
  677.  
  678. // ------------------------------------- END GLOBAL BOAT EQUATIONS AND FUNCTIONS---
  679.  
  680. ///////////////////////////////////////////////////
  681. // HUD SETTINGS //////////////////////////////////
  682. // you don't want to modify these settings //////
  683. ////////////////////////////////////////////////
  684.  
  685. // UPDATE HUD - Main HUD routine and colour management
  686. updateHUD() {
  687. string dataString;
  688. float compass=PI_BY_TWO-zRotAngle;
  689. float effcoeff;
  690.  
  691. string rgn = llGetRegionName();
  692. string blank = " ";
  693. float efficiency;
  694. string ratio;
  695. float derivatesheetAngle=sheetAngle;
  696.  
  697. //CALCULATE SPINNAKER EFFECTS ON EFFICIENCY
  698.  
  699. //Spinnaker tweak weighs 1/3 of global sheet
  700. if (Tack=="Starb'd") {
  701. derivatesheetAngle+=(CurSpin/3); //Starboards Spinnaker Tweak
  702. }
  703. if (Tack=="Port") {
  704. derivatesheetAngle-=(CurSpin/3); //Port Spinnaker Tweak
  705. }
  706.  
  707. //ACTUAL EFFICIENCY CALCULATION including spinnaker tweaks
  708. efficiency = llFabs(appwindAngle)*RAD_TO_DEG/derivatesheetAngle;
  709. if ((efficiency) < 0) {
  710. efficiency = efficiency * -1;
  711. }
  712.  
  713. compass=PI_BY_TWO-zRotAngle;
  714. while (compass<0) compass+=TWO_PI;
  715. dataString = " "; //clean hud message on startup
  716. currentString = " "; //clean hud storage on startup
  717.  
  718. //HUD COMPASS CONVERSION
  719.  
  720. float hudcompass =((integer)(compass*RAD_TO_DEG));
  721. string huddirection;
  722. if ((hudcompass) <= 360) {
  723. huddirection="North";
  724. }
  725. if ((hudcompass) <= 315) {
  726. huddirection="Northwest";
  727. }
  728. if ((hudcompass) <= 275) {
  729. huddirection="West";
  730. }
  731. if ((hudcompass) <= 230) {
  732. huddirection="Southwest";
  733. }
  734. if ((hudcompass) <= 185) {
  735. huddirection="South";
  736. }
  737. if ((hudcompass) <= 140) {
  738. huddirection="SouthEast";
  739. }
  740. if ((hudcompass) <= 95) {
  741. huddirection="East";
  742. }
  743. if ((hudcompass) <= 50) {
  744. huddirection="Northeast";
  745. }
  746. if ((hudcompass) <= 5) {
  747. huddirection="North";
  748. }
  749.  
  750. // STANDARD HUD STRING CONSTRUCTION ROUTINE
  751.  
  752. if (ADV_HUD==FALSE) {
  753.  
  754. // efficiency positive convert and ratio calculation
  755. if ((efficiency) < 0) {
  756. efficiency = efficiency * -1;
  757. }
  758. ratio = llGetSubString ((string)efficiency, 0, 3);
  759.  
  760. hudcolour=<1,1,1>; //default hudcolour
  761. dataString+="-> "+huddirection+" "; //add a direction string
  762. dataString+="( " +(string)((integer)(compass*RAD_TO_DEG))+"° )\n "; //add compass degrees
  763. dataString+="| "+visualAid+" | Speed "+llGetSubString((string)(llVecMag(groundSpeed*convert)),0,3)+units+"\n"; //add boat speed
  764. dataString+=(windType)+" "+(windRose)+"BWind\n"; //add BWind wind preset
  765.  
  766. //trailing blanks
  767. dataString+=blank+"\n";
  768. dataString+=blank+"\n";
  769.  
  770. }
  771.  
  772. // ADVANCED HUD STRING CONSTRUCTION ROUTINE
  773.  
  774. if (ADV_HUD==TRUE) {
  775.  
  776. // efficiency positive convert
  777. if ((efficiency) < 0) {
  778. efficiency = efficiency * -1;
  779. }
  780.  
  781. hudcolour=<1,1,1>; //default hudcolour
  782. dataString+="-> "+huddirection+" "; //add a direction string
  783. dataString+="( " +(string)((integer)(compass*RAD_TO_DEG))+"° )\n "; //add compass degrees
  784. dataString+="| "+visualAid+" | Speed "+llGetSubString((string)(llVecMag(groundSpeed*convert)),0,3)+units+" - "; //add boat speed
  785. dataString+=(windType)+" "+(windRose)+"BWind\n"; //add BWind wind preset
  786. dataString+="True Wind Angle " +(string)((integer)(truewindAngle*RAD_TO_DEG))+"° - "; //add True Wind
  787. dataString+="App. Wind Angle " +(string)((integer)(llFabs(appwindAngle)*RAD_TO_DEG))+"°\n"; //add Apparent Wind
  788. if (AWI1 > 0)
  789. {
  790. setAWI(appwindAngle*RAD_TO_DEG);
  791. }
  792.  
  793. ratio = llGetSubString ((string)efficiency, 0, 3); //display efficiency conversion
  794. dataString+="Wind/Sheet ratio " +ratio+ " - Sheet Angle "+((string)(sheetAngle))+"°\n"; //add Efficiency and Sheet Angle
  795.  
  796. //trailing blanks
  797. dataString+=blank+"\n";
  798. dataString+=blank+"\n";
  799.  
  800.  
  801. }
  802.  
  803. //---------- END HUD CONSTRUCTION ROUTINE
  804.  
  805. // HUD Colour Manager - This activates the HUD's virtual telltale function and affects ACTUAL BOAT'S SPEED WHILE TRIMMING
  806. // THIS ROUTINE IS VITAL FOR YOUR BOAT PERFORMANCE... THIS SETS THE BOAT'S SPEED WHEN YOU TRIM SAILS
  807.  
  808. // too tight - cyan - this is good as it is...
  809. if ((efficiency) < 25.0) {
  810. hudcolour=<0,1,1>;
  811. // dataString=currentString; //update hud message on activation
  812. visualAid="<>"; //help symbol for colour visual impaired - immediate feel of TOO TIGHT
  813. speedTweak=0.3; //MODIFY THIS VALUE ACCORDING TO YOUR NEEDS... TWEAKS BOAT'S SPEED
  814. }
  815.  
  816. // optimal - green - INCREASE THIS (never over 3) for easier apparent wind sailing
  817. // LOWER THIS (never below 2) for a more demanding trim activity
  818. if ((efficiency) < 2.5) {
  819. hudcolour=<0,1,0>;
  820. // dataString=currentString; //update hud message on activation
  821. visualAid="="; //help symbol for colour visual impaired - immediate feel of OPTIMAL
  822. speedTweak=1.0; //MODIFY THIS VALUE ACCORDING TO YOUR NEEDS... TWEAKS BOAT'S SPEED
  823.  
  824. //SPINNAKER Boost/De-Boost
  825. if (SPIN_UP==TRUE) {
  826. if ((sheetAngle < 65)) {
  827. speedTweak+=0.3;
  828. }
  829. if ((sheetAngle > 65)) {
  830. speedTweak+=0.0;
  831. }
  832. if ((sheetAngle < 50)) {
  833. speedTweak-=1.0; //original 0.5
  834. if (speedTweak < 0) speedTweak = 0.00001;
  835. }
  836. }
  837.  
  838. }
  839.  
  840. // off optimal - yellow - here the sheet is too loose, but your boat will still sail quite well
  841. if ((efficiency) < 1.7) {
  842. hudcolour=<1,1,0>;
  843. // dataString=currentString; //update hud message on activation
  844. visualAid="><"; //help symbol for colour visual impaired - immediate feel of TOO LOOSE
  845. speedTweak=0.7; //MODIFY THIS VALUE ACCORDING TO YOUR NEEDS... TWEAKS BOAT'S SPEED
  846. }
  847.  
  848. // too loose - red - oh yes this is very bad... the boat will almost stop sailing :)
  849. if ((efficiency) < 1.2) {
  850. hudcolour=<1,0,0>;
  851. // dataString=currentString; //update hud message on activation
  852. visualAid=">><<"; //help symbol for colour visual impaired - immediate feel of WAY TOO LOOSE
  853. speedTweak=0.3; //MODIFY THIS VALUE ACCORDING TO YOUR NEEDS... TWEAKS BOAT'S SPEED
  854. }
  855.  
  856. //display hud string - HERE WE START HUD
  857. llSetText(dataString,(vector)hudcolour,1.0);
  858. currentString=dataString; //save current HUD message
  859.  
  860. //Tacking animation management - HERE YOU CAN DECTIVATE THE TACKING ANIMATION - JUST COMMENT (//) THE FOLLOWING LINES
  861. // rather than doing that, it's configurable with a runtime flag now... set that up top in the startup.
  862. if (Tacking)
  863. {
  864. if (-sailingAngle > 0) {
  865. if ((llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) && llGetAgentSize(llGetPermissionsKey()) != ZERO_VECTOR) {
  866. llStopAnimation("bbk_helmsman");
  867. llStartAnimation ("bbk_helmstack");
  868. }
  869. }
  870. if (-sailingAngle < 0) {
  871. if ((llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) && llGetAgentSize(llGetPermissionsKey()) != ZERO_VECTOR) {
  872. llStopAnimation("bbk_helmstack");
  873. llStartAnimation ("bbk_helmsman");
  874. }
  875. }
  876. }
  877. }
  878.  
  879.  
  880. // ---------------------------- END HUD SETTINGS ---
  881.  
  882. //////////////////////////////////////////////////////////////////////////////////////////////
  883. // SCRIPT TRAPPING ROUTINE - state default //////////////////////////////////////////////////
  884. ////////////////////////////////////////////////////////////////////////////////////////////
  885.  
  886. default {
  887.  
  888. //get boat parts status
  889. state_entry() {
  890. getLinkNums();
  891. llSetText("",ZERO_VECTOR,1.0);
  892. startup();
  893. llSetStatus(STATUS_BLOCK_GRAB,TRUE);
  894. }
  895.  
  896. //reset boat
  897. on_rez(integer param) {
  898. llResetScript();
  899. }
  900.  
  901. //OWNER CHECK AND STATUS
  902. changed(integer change) {
  903. avatar=llAvatarOnSitTarget();
  904. if (change & CHANGED_LINK) {
  905. if (avatar==NULL_KEY) {
  906. if (!(llGetAgentInfo(owner) & AGENT_ON_OBJECT)) {
  907. if (SAIL_UP)
  908. {
  909. lowerSail();
  910. llMessageLinked(SPINNAKER,1000,"",NULL_KEY); //drop spinnaker/W reset
  911. }
  912. if (permSet) llReleaseControls();
  913. permSet=FALSE;
  914. llMessageLinked(LINK_SET, 70400, "", NULL_KEY);
  915. llResetScript();
  916. }
  917. }
  918. else {
  919. if (ownerVersion && avatar!=owner) llWhisper(0,"Only the owner can operate this boat.");
  920. else if ((llGetAgentInfo(owner) & AGENT_ON_OBJECT)) {
  921. llMessageLinked(SPINNAKER,1000,"",NULL_KEY); //drop spinnaker/W reset
  922. llWhisper(0,"Say raise to start sailing, help for sailing commands...");
  923. llWhisper(0,"BWind System defaults to East Wind, 15 Knots...");
  924.  
  925. if (llAvatarOnSitTarget()==owner) llRequestPermissions(owner,PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION | PERMISSION_CONTROL_CAMERA);
  926. }
  927. }
  928. }
  929. }
  930.  
  931.  
  932. //BOAT CONTROLS SETUP
  933. run_time_permissions(integer perms) {
  934. if (perms & (PERMISSION_TAKE_CONTROLS)) {
  935.  
  936. llClearCameraParams();
  937.  
  938. llSetCameraParams([
  939. CAMERA_ACTIVE, 1, // 0=INACTIVE 1=ACTIVE
  940. CAMERA_BEHINDNESS_ANGLE, 15.0, // (0 to 180) DEGREES
  941. CAMERA_BEHINDNESS_LAG, 1.0, // (0 to 3) SECONDS
  942. CAMERA_DISTANCE, 6.0, // ( 0.5 to 10) METERS
  943. CAMERA_PITCH, 20.0, // (-45 to 80) DEGREES
  944. CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
  945. CAMERA_POSITION_LAG, 0.05, // (0 to 3) SECONDS
  946. CAMERA_POSITION_THRESHOLD, 30.0, // (0 to 4) METERS
  947. CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
  948. CAMERA_FOCUS_LAG, 0.01 , // (0 to 3) SECONDS
  949. CAMERA_FOCUS_THRESHOLD, 0.01, // (0 to 4) METERS
  950. CAMERA_FOCUS_OFFSET, <0.0,0.0,0.0> // <-10,-10,-10> to <10,10,10> METERS
  951. ]);
  952.  
  953. llTakeControls(CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT |
  954. CONTROL_ROT_LEFT | CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP,TRUE,FALSE);
  955. permSet=TRUE;
  956. if (permSet) llStartAnimation("bbk_helmsman");
  957. llMessageLinked(LINK_SET, 70400, "", avatar);
  958. llMessageLinked(SPINNAKER,1000,"",NULL_KEY); //drop spinnaker/W reset
  959. }
  960. }
  961.  
  962. // ------------------------ END STATE DEFAULT DECLARATIONS ---
  963.  
  964. ////////////////////////////////////////////////////////////////////
  965. // MAIN BOAT LISTENER /////////////////////////////////////////////
  966. //////////////////////////////////////////////////////////////////
  967.  
  968. // YOU BETTER NEVER EDIT THE FOLLWING LINES UNLESS YOU KNOW WHAT TO DO :)
  969.  
  970. listen(integer channel, string name, key id, string msg)
  971. {
  972. if (channel==0)
  973. {
  974. if (owner==id & llAvatarOnSitTarget()==owner)
  975. {
  976. if (llGetAgentInfo(owner) & AGENT_ON_OBJECT)
  977. {
  978. if (llGetSubString(msg,0,4)=="sheet")
  979. {
  980. incr=(integer)llDeleteSubString(msg,0,4);
  981. sheetAngle+=incr;
  982. if (sheetAngle>90) sheetAngle=90;
  983. }
  984. //MESSAGE raise - hey we DO want to sail huh?
  985. else if (msg=="raise")
  986. {
  987. llMessageLinked(LINK_ALL_CHILDREN , 0, "start", NULL_KEY);
  988. sailing=TRUE;
  989. if (!permSet) llRequestPermissions(owner,PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION);
  990. permSet=TRUE;
  991. llSetStatus(STATUS_PHYSICS,TRUE);
  992. raiseSail();
  993. llSetTimerEvent(timerFreq);
  994. }
  995.  
  996. // SPINNAKER HOIST/DROP
  997. else if (msg=="spin" && SPIN_UP) DropSpin();
  998. else if (msg=="spin" && !SPIN_UP) HoistSpin();
  999.  
  1000. //SPINNAKER TRIM
  1001. else if (msg=="spin+") TrimSpinPlus();
  1002. else if (msg=="spin-") TrimSpinMinus();
  1003.  
  1004. //GYBE POLE
  1005. else if (msg=="gybe")
  1006. {
  1007. if (SPIN_UP==TRUE)
  1008. {
  1009. llMessageLinked(SPINNAKER,1004,"",NULL_KEY); //hoist spinnaker
  1010. if (-sailingAngle > 0) llMessageLinked(POLE,1003,"",NULL_KEY);
  1011. if (-sailingAngle < 0) llMessageLinked(POLE,1004,"",NULL_KEY);
  1012. CurSpin=0;
  1013. }
  1014. }
  1015.  
  1016. //MESSAGE lower - okay now we want physics ON but no sailing...
  1017. else if (msg=="lower")
  1018. {
  1019. sailing=FALSE;
  1020. lowerSail();
  1021. }
  1022. else if (msg=="moor")
  1023. {
  1024. llMessageLinked(LINK_ALL_CHILDREN , 0, "stop", NULL_KEY);
  1025. moor();
  1026. llSetTimerEvent(0);
  1027. if (SAIL_UP) lowerSail();
  1028. llResetScript();
  1029. }
  1030. // course hold
  1031. else if (msg=="hold")
  1032. {
  1033. courseHold = TRUE;
  1034. courseHoldValue = zRotAngle*RAD_TO_DEG;
  1035. courseHoldValue = (450.0 - courseHoldValue)%360.0;
  1036. llWhisper(0,"Course Hold enabled:" + (string)courseHoldValue);
  1037. }
  1038.  
  1039. //BOAT ID Setter
  1040. else if (llGetSubString(msg,0,1)=="id")
  1041. {
  1042. if (llGetSubString(msg,3,-1)!="off")
  1043. {
  1044. idStr=llGetSubString(msg,3,-1);
  1045. string tmp=boatName+" #"+idStr;
  1046. llSetObjectName(tmp);
  1047. llWhisper(0,"New Boat ID :"+tmp);
  1048. }
  1049. }
  1050.  
  1051. //START bbk_helmsman ANIMATION
  1052. else if (llGetSubString(msg,0,3)=="anim")
  1053. {
  1054. if (llGetSubString(msg,5,-1)=="off")
  1055. {
  1056. }
  1057. else if (llGetSubString(msg,5,-1)=="on")
  1058. {
  1059. if (permSet) llStartAnimation("bbk_helmsman"); // change thise pose/animation name if needed...
  1060. }
  1061. }
  1062.  
  1063. }
  1064. }
  1065.  
  1066. //-------------------------------- END MAIN BOAT LISTENER ---
  1067.  
  1068. ///////////////////////////////////////////////////////////////
  1069. // BWind Engine - WIND DIRECTION PRESETS /////////////////////
  1070. //////////////////////////////////////////////////////////////
  1071.  
  1072. //wind direction in degrees - North = 0°
  1073. //you don't want to modify the following presets unless you want to add other BWind directions
  1074.  
  1075. // setter on or off, locks out the rest of the settings
  1076.  
  1077. if (msg=="setter")
  1078. {
  1079. llWhisper(0,"BWind using weather buoy");
  1080. useSetter=TRUE;
  1081. lock = TRUE;
  1082. setWindFromBuoy(); // will set all the preset variables based on set wind vector
  1083.  
  1084. }
  1085. if (msg=="setoff")
  1086. {
  1087. llWhisper(0,"BWind setter disengaged");
  1088. llListenRemove(windh); // stop listening, save lag
  1089. useSetter=FALSE; // stop setting variables
  1090. lock = FALSE; // allow the manual BWind setter to work again
  1091.  
  1092. }
  1093.  
  1094. // command set here
  1095.  
  1096. if (lock==FALSE) {
  1097.  
  1098. if (msg=="n") {
  1099. windRose ="North ";
  1100. windDir=(90*DEG_TO_RAD);
  1101. llWhisper(0,"BWind now blowing from North");
  1102. }
  1103. if (msg=="nw") {
  1104. windRose ="Northwest ";
  1105. windDir=(135*DEG_TO_RAD);
  1106. llWhisper(0,"BWind now blowing from Northwest");
  1107. }
  1108. if (msg=="ne") {
  1109. windRose ="Northeast ";
  1110. windDir=(45*DEG_TO_RAD);
  1111. llWhisper(0,"BWind now blowing from Northeast");
  1112. }
  1113. if (msg=="e") {
  1114. windRose ="East ";
  1115. windDir=(0*DEG_TO_RAD);
  1116. llWhisper(0,"BWind now blowing from East");
  1117. }
  1118. if (msg=="s") {
  1119. windRose ="South ";
  1120. windDir=(270*DEG_TO_RAD);
  1121. llWhisper(0,"BWind now blowing from South");
  1122. }
  1123. if (msg=="sw") {
  1124. windRose ="Southwest ";
  1125. windDir=(225*DEG_TO_RAD);
  1126. llWhisper(0,"BWind now blowing from Southwest");
  1127. }
  1128. if (msg=="se") {
  1129. windRose ="Southeast ";
  1130. windDir=(315*DEG_TO_RAD);
  1131. llWhisper(0,"BWind now blowing from Southeast");
  1132. }
  1133. if (msg=="w") {
  1134. windRose ="West ";
  1135. windDir=(180*DEG_TO_RAD);;
  1136. llWhisper(0,"BWind now blowing from West");
  1137. }
  1138. }
  1139.  
  1140.  
  1141. // ----------------------------- END WIND DIRECTION PRESETS ---
  1142.  
  1143. ///////////////////////////////////////////////////////////////
  1144. // BWind Engine - BWIND SPEED PRESETS ////////////////////////
  1145. //////////////////////////////////////////////////////////////
  1146.  
  1147. //this is where you have to mod to set your desired BWIND Wind PRESETS
  1148. // REMEBER THAT THE BOAT SPEED IS SET IN THE TRIM/HUD ROUTINE ABOVE - here you set the max speed only for each wind preset...
  1149. //You may add other wind speeds at will, while I think you have plenty...
  1150. //WWC racing module preset will be added here upon release... (currently under development)
  1151.  
  1152. //8 KNOTS PRESET
  1153.  
  1154. if (msg=="8") {
  1155. //primary parameters - self explanatory
  1156. windSpeed=4.12; //PRECALCULATED WIND SPEED
  1157. maxSpeed=4.0; //YOUR BOAT MAX SPEED FOR THIS WIND PRESET
  1158. heelTweak=0.7; //YOUR BOAT MAX HEEL FOR THIS WIND PRESET
  1159.  
  1160. //Preset Boat Physics
  1161. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift; this is useful for multihull boats
  1162.  
  1163. //Preset running... return wind speed status... - THIS BUILDS THE HUD STRING....
  1164. llWhisper(0,"BWind speed set to 8 Knots");
  1165. windType="8 Knots"; // 8 Knots
  1166. }
  1167.  
  1168. // 11 KNOTS PRESET
  1169.  
  1170. if (msg=="11") {
  1171.  
  1172. //primary parameters - see above for explanation (8 Knots Preset)
  1173. windSpeed=5.70;
  1174. maxSpeed=4.5;
  1175. heelTweak=0.8;
  1176.  
  1177. //Preset Boat Physics
  1178. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift
  1179.  
  1180. //Preset running... return wind speed status...
  1181. llWhisper(0,"BWind speed set to 11 Knots");
  1182. windType="11 Knots"; // 11 Knots
  1183. }
  1184.  
  1185. // 15 KNOTS PRESET
  1186. // VERY IMPORTANT !!!
  1187. // REMEMBER ! : FOLLOWING VALUES MUST BE THE SAME YOU SET IN DEFAULT WIND SPEED AT LINE 143
  1188.  
  1189. if (msg=="15") {
  1190.  
  1191. //primary parameters - see above for explanation (8 Knots Preset)
  1192. windSpeed=7.75;
  1193. maxSpeed=5.5;
  1194. heelTweak=0.85;
  1195.  
  1196. //Preset Boat Physics
  1197. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift
  1198.  
  1199. //Preset running... return wind speed status...
  1200. llWhisper(0,"BWind speed set to 15 Knots");
  1201. windType="15 Knots"; // 15 Knots
  1202. }
  1203.  
  1204. // 18 KNOTS PRESET
  1205.  
  1206. if (msg=="18") {
  1207.  
  1208. //primary parameters - see above for explanation (8 Knots Preset)
  1209. windSpeed=9.30;
  1210. maxSpeed=6.5;
  1211. heelTweak=0.95;
  1212.  
  1213. //Preset Boat Physics
  1214. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift
  1215.  
  1216. //Preset running... return wind speed status...
  1217. llWhisper(0,"BWind speed set to 18 Knots");
  1218. windType="18 Knots"; // 18 Knots
  1219. }
  1220.  
  1221. // 21 KNOTS PRESET
  1222.  
  1223. if (msg=="21") {
  1224.  
  1225. //primary parameters - see above for explanation (8 Knots Preset)
  1226. windSpeed=9.5;
  1227. maxSpeed=7.0;
  1228. heelTweak=1.0;
  1229.  
  1230. //Preset Boat Physics
  1231. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift
  1232.  
  1233. //Preset running... return wind speed status...
  1234. llWhisper(0,"BWind speed set to 21 Knots");
  1235. windType="21 Knots"; // 21 Knots
  1236. }
  1237.  
  1238. // 25 KNOTS PRESET
  1239.  
  1240. if (msg=="25") {
  1241.  
  1242. //primary parameters - see above for explanation (8 Knots Preset)
  1243. windSpeed=11.3;
  1244. maxSpeed=7.5;
  1245. heelTweak=1.1;
  1246.  
  1247. //Preset Boat Physics
  1248. //llSetVehicleFloatParam (VEHICLE_HOVER_HEIGHT,seaLevel); //Vehicle Lift
  1249.  
  1250. //Preset running... return wind speed status...
  1251. llWhisper(0,"BWind speed set to 25 Knots");
  1252. windType="25 Knots"; // 25 Knots
  1253.  
  1254. }
  1255.  
  1256.  
  1257.  
  1258. // ------------------------------ END WIND SPEED PRESETS ---
  1259.  
  1260.  
  1261. //////////////////////////////////////////////////////////////
  1262. // UTILITIES ////////////////////////////////////////////////
  1263. ////////////////////////////////////////////////////////////
  1264.  
  1265. //Help Message
  1266. //here you may build your own help message, shown when you type 'help' without quotes in chat...
  1267.  
  1268. if (msg=="help") {
  1269. helpString = " ";
  1270. helpString+="SAY IN CHAT...\n";
  1271. helpString+="------------------------------------------------------------------------------------------------\n";
  1272. helpString+="raise - start sailing\n";
  1273. helpString+="lower - lower sails (press arrow keys to move around)\n";
  1274. helpString+="moor - stop sailing\n";
  1275. helpString+="hold - hold current heading\n";
  1276. helpString+="------------------------------------------------------------------------------------------------\n";
  1277. helpString+="n,s,e,w,nw,ne,sw,se,setter,setoff - set BWind direction\n";
  1278. helpString+="8,11,15,18,21,25 - set BWind speed\n";
  1279. helpString+="id nnaa (ex. 12AB) - set boat ID\n";
  1280. helpString+="hud - hud switch (standard/advanced)\n";
  1281. helpString+="spin - hoist/drop Spinnaker (press PgUp & PgDn to trim)\n";
  1282. helpString+="gybe - gybe Spinnaker's pole upon tack\n";
  1283. helpString+="------------------------------------------------------------------------------------------------\n";
  1284. helpString+="HUD colour shows trim settings :\n";
  1285. helpString+="|>><<| red = too loose - |><| yellow = off optimum - \n";
  1286. helpString+="|=| green = optimum - |<>| cyan = too tight\n";
  1287. helpString+="------------------------------------------------------------------------------------------------\n";
  1288. llWhisper(0,helpString);
  1289.  
  1290. }
  1291.  
  1292. // HUD Switch -switch between the two alternative HUD modes : standard and advanced
  1293.  
  1294. else if (msg=="hud" && ADV_HUD) ADV_HUD=FALSE;
  1295. else if (msg=="hud" && !ADV_HUD) ADV_HUD=TRUE;
  1296.  
  1297. }
  1298.  
  1299. if (channel==-54001) // setter buoy, if present, is on this channel
  1300. {
  1301. if (useSetter==TRUE) // don't do anything unless the setter is active
  1302.  
  1303. {
  1304. list lines=llParseString2List(msg,["\n"],[]);
  1305.  
  1306. if (llList2String(lines,0)=="wind") // look for a wind message
  1307. {
  1308. list parse=llParseString2List(llList2String(lines,1),["=",";","/"],[]);
  1309. string var=llList2String(parse,0);
  1310. string val=llList2String(parse,1);
  1311. if (var=="wvel") // take wind velocity as a vector
  1312. {
  1313. wind=(vector)val;
  1314. windSpeed = llVecMag(wind); // m/s for the calculations
  1315. maxSpeed = windSpeed*0.75; // generically, max speed is 3/4 the wind speed
  1316. windSpeed = windSpeed*1.94; // change wind speed to knots
  1317. windDir = ((llAtan2(wind.x,wind.y)* RAD_TO_DEG)+180.0); // true direction
  1318. windType = llGetSubString((string)windSpeed,0,4) + " Knots";
  1319.  
  1320.  
  1321. if (windSpeed > 25.0) // do the heel tweaks based on windspeed
  1322. {
  1323. heelTweak = 1.2;
  1324. }
  1325. else
  1326. {
  1327. if (windSpeed > 21.0)
  1328. {
  1329. heelTweak = 1.1;
  1330. }
  1331. else
  1332. {
  1333. if (windSpeed > 18.0)
  1334. {
  1335. heelTweak = 1.0;
  1336. }
  1337. else
  1338. {
  1339. if (windSpeed > 15.0)
  1340. {
  1341. heelTweak = 0.95;
  1342. }
  1343. else
  1344. {
  1345. if (windSpeed > 11.0)
  1346. {
  1347. heelTweak = 0.85;
  1348. }
  1349. else
  1350. {
  1351. if (windSpeed > 8.0)
  1352. {
  1353. heelTweak = 0.8;
  1354. }
  1355. else
  1356. {
  1357. heelTweak = 0.7;
  1358. }
  1359. }
  1360. }
  1361. }
  1362. }
  1363. }
  1364.  
  1365.  
  1366.  
  1367. if (windDir > 336.0) // now set the compass rose too
  1368. {
  1369. windRose = " North ";
  1370. }
  1371. else
  1372. {
  1373. if (windDir > 290.0)
  1374. {
  1375. windRose = " Northwest ";
  1376. }
  1377. else
  1378. {
  1379. if (windDir > 250.0)
  1380. {
  1381. windRose = " West ";
  1382. }
  1383. else
  1384. {
  1385. if (windDir > 202)
  1386. {
  1387. windRose = " Southwest ";
  1388. }
  1389. else
  1390. {
  1391. if (windDir > 157.0)
  1392. {
  1393. windRose = " South ";
  1394. }
  1395. else
  1396. {
  1397. if (windDir > 112.0)
  1398. {
  1399. windRose = " Southeast ";
  1400. }
  1401. else
  1402. {
  1403. if (windDir > 67.0)
  1404. {
  1405. windRose = " East ";
  1406. }
  1407. else
  1408. {
  1409. if (windDir > 22.0)
  1410. {
  1411. windRose = " Northeast ";
  1412. }
  1413. else
  1414. {
  1415. windRose = " North ";
  1416. }
  1417. }
  1418. }
  1419. }
  1420. }
  1421. }
  1422. }
  1423. }
  1424.  
  1425.  
  1426. windRose = "from " + llGetSubString((string)windDir,0,4) + "º " + windRose;
  1427. // finally the system actually wants the wind direction in radians so convert it back
  1428. // also the whole compass is bass ackwards and offset by 90 degrees being east so
  1429. // the whole damn thing has to rotate and then go to degrees
  1430.  
  1431. windDir = (450.0 - windDir)%360.0;
  1432.  
  1433.  
  1434. //windDir = windDir + 90;
  1435.  
  1436. windDir = windDir*DEG_TO_RAD;
  1437. }
  1438. }
  1439. } }
  1440. }
  1441.  
  1442. // --------------------------------------- END UTILITIES ---
  1443.  
  1444. ///////////////////////////////////////////////////
  1445. // GLOBAL BOAT CONTROLS //////////////////////////
  1446. // you don't want to modify these settings //////
  1447. ////////////////////////////////////////////////
  1448.  
  1449. //Following section maps keyboard keys for boat control... I would NOT edit this section...
  1450.  
  1451.  
  1452. control(key id, integer held, integer change) {
  1453. //turning controls - LEFT AND RIGHT KEYS
  1454. if ( (change & held & CONTROL_LEFT) || (held & CONTROL_LEFT) || (change & held & CONTROL_ROT_LEFT) || (held & CONTROL_ROT_LEFT) ) {
  1455. if (courseHold)
  1456. {
  1457. courseHold = FALSE;
  1458. llWhisper(0,"disengaging course hold...");
  1459. }
  1460. if (sailing == FALSE) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<rotSpeed/2.0,0.0,rotSpeed>);
  1461. else llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<-rotSpeed,0.0,rotSpeed/1.5>); // left key hold - end
  1462. }
  1463. else if ( (change & held & CONTROL_RIGHT) || (held & CONTROL_RIGHT) || (change & held & CONTROL_ROT_RIGHT) || (held & CONTROL_ROT_RIGHT) ) {
  1464.  
  1465. if (courseHold)
  1466. {
  1467. courseHold = FALSE;
  1468. llWhisper(0,"disengaging course hold...");
  1469. }
  1470.  
  1471. if (sailing == FALSE) llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<-rotSpeed/2.0,0.0,-rotSpeed>);
  1472. else llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<rotSpeed,0.0,-rotSpeed/1.5>); // right key hold - end
  1473. }
  1474. else if ( (change & ~held & CONTROL_LEFT) || (change & ~held & CONTROL_ROT_LEFT) ) {
  1475. llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,0.0>); // left key touched - end
  1476. }
  1477. else if ( (change & ~held & CONTROL_RIGHT) || (change & ~held & CONTROL_ROT_RIGHT) ) {
  1478. llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<0.0,0.0,0.0>); // right key touched - end
  1479. }
  1480. //sail/throttle controls - UP AND DOWN KEYS
  1481. if ( (held & CONTROL_FWD) && (held & CONTROL_UP) ) {
  1482. if (sailing == TRUE) {
  1483. sheetAngle+=7;
  1484. if (sheetAngle>90) sheetAngle=90;
  1485. }
  1486. else
  1487. {
  1488. setTach(5.0);
  1489. llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<5.0,0,0>);
  1490. }
  1491. } // up key hold - end
  1492. else if ( (held & CONTROL_FWD) || (change & held & CONTROL_FWD) ) {
  1493. if (sailing == TRUE) {
  1494. sheetAngle+=2;
  1495. if (sheetAngle>90) sheetAngle=90;
  1496. //llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<5.0,0.0,0.0>);
  1497. } else {
  1498. setTach(5.0);
  1499. llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<5.0,0,0>);
  1500. }
  1501.  
  1502. } // up key touched - end
  1503. else if ( (held & CONTROL_BACK) && (held & CONTROL_UP) ) {
  1504.  
  1505. if (sailing == TRUE) {
  1506. sheetAngle-=7;
  1507. if (sheetAngle<5) sheetAngle=5;
  1508. }
  1509. else
  1510. {
  1511. setTach(0.0);
  1512. }
  1513. } // down key hold - end
  1514. else if ( (held & CONTROL_BACK) || (change & held & CONTROL_BACK) ) {
  1515. if (sailing == TRUE) {
  1516. sheetAngle-=2;
  1517. if (sheetAngle<5) sheetAngle=5;
  1518. //llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<-5.0,0.0,0.0>);
  1519. } else {
  1520. setTach(0.0);
  1521. llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<-5.0,0,0>);
  1522. }
  1523. } // down key touched - end
  1524.  
  1525. //PGUP/PGDN Spinnaker control
  1526. else if (change & held & CONTROL_UP) {
  1527. TrimSpinPlus();
  1528. }
  1529. else if (change & held & CONTROL_DOWN) {
  1530. TrimSpinMinus();
  1531. }
  1532.  
  1533. }
  1534.  
  1535. // ------------------------------------- END GLOBAL BOAT CONTROLS ---
  1536.  
  1537. ///////////////////////////////////////////////////
  1538. // GLOBAL BOAT TIMER /////////////////////////////
  1539. // you don't want to modify these settings //////
  1540. ////////////////////////////////////////////////
  1541.  
  1542. //IMPORTANT !!! THIS IS THE ACTUAL BOAT CYCLE INVOKING ALL SAILING ROUTINES
  1543. //WHATEVER YOU DELETE HERE WILL AFFECT ACTUAL ENGINE BEHAVIOUR
  1544. //HERE YOU MAY ADD YOUR OWN PERSONAL FUNCTIONS IF NEEDED AND YOU KNOW WHAT TO DO...
  1545.  
  1546.  
  1547. link_message(integer from,integer to,string msg,key id) {
  1548. }
  1549.  
  1550. timer() {
  1551. calcTrueWindAngle();
  1552. calcAppWindAngle(); // invoke wind angle calculation routine
  1553. if (SAIL_UP) calcBoomDelta(); // invoke sail trim calculation routine
  1554. calcHeelAngle(); // invoke heel calculation routine
  1555. calcSpeed(); // invoke speed calculation routine
  1556. calcLeeway(); // invoke leeway calculation routine
  1557. calcTurnRate(); // invoke turn rate routine
  1558. if (HUD_ON) updateHUD(); // update hud on cycle
  1559. llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<currSpeed,leeway,0>); // boat linear movement
  1560. llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<heelTorque,0.0,0.0>); // boat angular movement
  1561. if (courseHold) updateCourse(); // if AP is on, adjust course
  1562. setWindvane(windDir*RAD_TO_DEG);
  1563. }
  1564.  
  1565. // -------------------------------------- END GLOBAL BOAT TIMER ---
  1566.  
  1567.  
  1568.  
  1569. }
  1570.  
  1571. // ------------------------------------- END PROGRAMME -----------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement