Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion HoOpy Casino

Content

Warnings

  1. License not specified
  2. Unknown key 'licence' at https://wiki.alioth.net/img_auth.php/6/6f/HOopyCasino1.3.5.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Commanders who chose to dock with a HoOpy Casino are quickly ushered into the vast gaming halls, here to be offered the opportunity to win or lose credits in games of chance. Commanders who chose to dock with a HoOpy Casino are quickly ushered into the vast gaming halls, here to be offered the opportunity to win or lose credits in games of chance.
Identifier oolite.oxp.Murgh.HoOpyCasino oolite.oxp.Murgh.HoOpyCasino
Title HoOpy Casino HoOpy Casino
Category Dockables Dockables
Author Eric Walch, Murgh, CaptSolo, spara Eric Walch, Murgh, CaptSolo, spara
Version 1.3.5 1.3.5
Tags Casino, Gambling Casino, Gambling
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/HoOpy_Casino n/a
Download URL https://wiki.alioth.net/img_auth.php/6/6f/HOopyCasino1.3.5.oxz n/a
License
File Size n/a
Upload date 1610873331

Documentation

Also read http://wiki.alioth.net/index.php/HoOpy%20Casino

ReadMe.rtf

{\rtf1\ansi\deff3\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 Helvetica{\*\falt Arial};}{\f6\fnil\fprq2\fcharset0 FreeSans;}{\f7\fnil\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}}
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
{\stylesheet{\s0\snext0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057 Normal;}
{\s15\sbasedon0\snext16\ql\nowidctlpar\sb240\sa120\keepn\ltrpar\cf1\kerning1\dbch\af6\langfe1081\dbch\af7\afs24\loch\f4\fs28\lang2057 Heading;}
{\s16\sbasedon0\snext16\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\loch\f3\fs24\lang2057 Text Body;}
{\s17\sbasedon16\snext17\sl288\slmult1\ql\nowidctlpar\sb0\sa140\ltrpar\cf1\kerning1\dbch\af6\langfe1081\dbch\af7\afs24\loch\f3\fs24\lang2057 List;}
{\s18\sbasedon0\snext18\ql\nowidctlpar\sb120\sa120\ltrpar\cf1\i\kerning1\dbch\af6\langfe1081\dbch\af7\afs24\loch\f3\fs24\lang2057 Caption;}
{\s19\sbasedon0\snext19\ql\nowidctlpar\ltrpar\cf1\kerning1\dbch\af6\langfe1081\dbch\af7\afs24\loch\f3\fs24\lang2057 Index;}
}{\*\generator LibreOffice/5.2.0.4$Linux_X86_64 LibreOffice_project/20m0$Build-4}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr2016\mo8\dy29\hr18\min46}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab720
\viewscale110
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\pgwsxn11906\pghsxn16838\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
\formshade{\*\pgdscno0}\paperh16838\paperw11906\margl1440\margr1440\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn11906\pghsxn16838\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
{\*\ftnsep}\pgndec\pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b\dbch\af6\rtlch \ltrch\loch\fs34\loch\f5
Hoopy Casino}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\fs28\loch\f5
By Murg}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b0\dbch\af6\rtlch \ltrch\loch\fs28\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\fs28\loch\f5
Version 1.3.2}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\fs22\loch\f5
(Requires Oolite 1.80 or newer.)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b\dbch\af6\rtlch \ltrch\loch\fs34\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b\dbch\af6\rtlch \ltrch\loch\fs34\loch\f5
Overview}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Multi-billionaire and FurCorp heiress Magda DeMug first dabbled in commercial enterprises founding CoachWhip Inc. Her fleet of CoachWhip luxury liners provide a first class transport service to well-healed business executives, VIPs and anyone else who can afford the 5,000 Cr ticket price. Having established a profitable enterprise fleecing the idle rich, the heiress turned her acute feline business mind to the question of sucking credits from the pockets of the proletariat.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
The basic hull of the CoachWhip liner was completely stripped, removing the cargo bay, hyperspace drive and inter-system drive. A docking port was added and the internal structure re-fitted as a luxurious Casino. The platforms were then deployed in geo-stationary orbit near the main GalCop Station in technologically advanced systems throughout the eight galaxies. Thus was the Chain of HoOpy Casinos born. These dens of inequity are found in all systems with a Tech Level of 11 or more. In such a system, setting an Advanced Space Compass to C will locate the nearest HoOpy Casino.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b0\dbch\af6\rtlch \ltrch\loch\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b0\dbch\af6\rtlch \ltrch\loch\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b\dbch\af6\rtlch \ltrch\loch\fs34\loch\f5
The HoOpy Casino Chain}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Commanders who chose to dock with a HoOpy Casino are quickly ushered into the vast gaming halls, here to be offered the opportunity to win or lose credits in games of chance.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Some Commanders never leave the casino area of the station, claiming that they have a system to \u8216\'91beat the hoops\u8217\'92. These doomed lost souls can often be seen wagering their Credits, ship, left kidney or spouse on just one more throw of the hoops.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Commanders of a more level-headed nature visit HoOpy Casinos for the purpose of trading. Those who can resist the charms of the complementary drinks and scantily clad croupiers available in the main casino area of the orbital platform may engage in trading on the Station\u8217\'92s commodity market. The Casinos often have a surplus or deficient of certain goods and thus a canny trader can sometimes make more profit by off-loading or purchasing his cargo at the Casino rather than the system\u8217\'92s GalCop station.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
The Casino is protected by a reasonably strong shield, although it carries no weapons. The Casino Managment rely on the fact that the casino closely orbits the GalCop Station, which will launch Vipers to defend the orbital platform from attack. Additionally a small fleet of Security Sidewinders in HoOpy livery are stationed aboard to defend the Casino if need be.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b0\dbch\af6\rtlch \ltrch\loch\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
(Background story by Little Bear)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\b0\dbch\af6\rtlch \ltrch\loch\loch\f5

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
(Original JS scripting by Paul Wilkins & Eric Walch)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\dbch\af6\rtlch \ltrch\loch

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3) for Oolite 1.80 by CaptSolo & spara.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* New and retouched textures and flashy shader effects by CaptSolo. Shader by Griff, Neon sign model Arexic_Heretic. Docking bay by Griff.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* BGS docking tunnel texture by spara}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Sidewinder defenders updated to Griff's model.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Script restructured and updated to spawn with 1.80 populator by spara.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Station welcome screen is removed and games are moved to station interfaces (F4).}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Station AI tweaked to be more aggressive against attacking. Code borrowed from YAH.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Two new gambling games: Smuggler's Run dice game and Video Poker. Scripting by spara. Card model and textures by CaptSolo. Sound effects are borrowed from Oolite. Dice game graphics by spara with two screenshots by Cody and Redspear.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\rtlch \ltrch\loch

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3.1)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* New gambling game: Blackjack.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Backgrounds added to the gard games.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\rtlch \ltrch\loch

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{{\*\bkmkstart __DdeLink__38_506304518}{\*\bkmkend __DdeLink__38_506304518}\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3.2)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* New gambling game: hOopy Hold'em. }
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Market stripped to gems, gold and platinum. In 1.80 prices follow the main station rules. In 1.81 prices are 10% below main station. In other words market is solely meant for exchanging valuables to play credits, with 10% commission.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* AI rewitten to JS. Casino now cruises around the main station at the edge of the Aegis.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\rtlch \ltrch\loch

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3.3)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{{\*\bkmkstart __DdeLink__45_986228504}{\*\bkmkend __DdeLink__45_986228504}\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* AI finished.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar\rtlch \ltrch\loch

\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3.4)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* No shader neonsign added.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\hyphpar0\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
Update (1.3.}{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
5}{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
)}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\hyphpar0\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Holdem }{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
bugfixed}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar\hyphpar0\cf1\kerning1\dbch\af7\langfe1081\dbch\af7\afs24\alang1081\loch\f3\fs24\lang2057\ql\nowidctlpar\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\hyphpar0\ltrpar{\b0\dbch\af6\rtlch \ltrch\loch\loch\f5
* Shiny cards}
\par }

Equipment

This expansion declares no equipment. This may be related to warnings.

Ships

Name
CoachWhip hOopy Casino
casinoship_dockingbay
Neon Sign
hoopy_blackjack_card_back
Video Poker Card
hoopy_blackjack_card_pos10
hoopy_blackjack_card_pos11
hoopy_blackjack_card_pos12
hoopy_blackjack_card_pos13
hoopy_blackjack_card_pos14
hoopy_blackjack_card_pos15
hoopy_blackjack_card_pos16
hoopy_blackjack_card_pos17
hoopy_blackjack_card_pos18
hoopy_blackjack_card_pos19
hoopy_blackjack_card_pos2
hoopy_blackjack_card_pos20
hoopy_blackjack_card_pos21
hoopy_blackjack_card_pos22
hoopy_blackjack_card_pos23
hoopy_blackjack_card_pos24
hoopy_blackjack_card_pos25
hoopy_blackjack_card_pos26
hoopy_blackjack_card_pos27
hoopy_blackjack_card_pos28
hoopy_blackjack_card_pos29
hoopy_blackjack_card_pos3
hoopy_blackjack_card_pos30
hoopy_blackjack_card_pos31
hoopy_blackjack_card_pos32
hoopy_blackjack_card_pos33
hoopy_blackjack_card_pos34
hoopy_blackjack_card_pos35
hoopy_blackjack_card_pos36
hoopy_blackjack_card_pos37
hoopy_blackjack_card_pos38
hoopy_blackjack_card_pos39
hoopy_blackjack_card_pos4
hoopy_blackjack_card_pos40
hoopy_blackjack_card_pos41
hoopy_blackjack_card_pos42
hoopy_blackjack_card_pos43
hoopy_blackjack_card_pos44
hoopy_blackjack_card_pos45
hoopy_blackjack_card_pos46
hoopy_blackjack_card_pos47
hoopy_blackjack_card_pos48
hoopy_blackjack_card_pos49
hoopy_blackjack_card_pos5
hoopy_blackjack_card_pos50
hoopy_blackjack_card_pos51
hoopy_blackjack_card_pos52
hoopy_blackjack_card_pos53
hoopy_blackjack_card_pos54
hoopy_blackjack_card_pos55
hoopy_blackjack_card_pos6
hoopy_blackjack_card_pos7
hoopy_blackjack_card_pos8
hoopy_blackjack_card_pos9
Video Blackjack Card
hoopy_casino_blackjack_intro
Video Poker Card
hoopy_casino_holdem_intro
Video Poker Card
hoopy_casino_poker_card_spin
hoopy_holdem_card_back
Video Hold'em Card
hoopy_holdem_card_pos2
hoopy_holdem_card_pos3
hoopy_holdem_card_pos4
hoopy_holdem_card_pos5
hoopy_holdem_card_pos6
hoopy_holdem_card_pos7
hoopy_holdem_card_pos8
hoopy_holdem_card_pos9
hoopy_poker_card_back
Video Poker Card
hoopy_poker_card_pos2
hoopy_poker_card_pos3
hoopy_poker_card_pos4
hoopy_poker_card_pos5
Sidewinder Casino Security

Models

This expansion declares no models. This may be related to warnings.

Scripts

Path
Scripts/hoopy_blackjack.js
"use strict";

this.name = "hoopy_blackjack";
this.author = "spara";
this.copyright = "2014 spara";
this.license     = "CC BY-NC-SA 4.0"; 

//add interface
this.startUpComplete = this.shipExitedWitchspace = function() {
	var casinos = system.shipsWithPrimaryRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-blackjack",{
				title: "Blackjack",
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-blackjack-summary"),
				callback: this.$intro.bind(this)
			});
		}
	}
}

//init a new deck
this.$virginDeck = function() {
	var deck = new Array();
	var suits = ["triangle", "crescent", "square", "star"];
	for (var i = 0; i < 4; i++) {
		for (var j = 1; j < 14; j++) {
			var card = new Object();
			card.suit = suits[i];
			card.rank = j;
			card.double = 0; 
			card.hide = 0;
			if (j > 10) card.value = 10;
			else if (j === 1) card.value = 11;
			else card.value = card.rank;
			deck.push(card);
		}
	}
	return deck;
}

//calculate the value of a hand
this.$calculateHandValue = function(cards) {
	var finished = false;
	while (!finished) {
		var sum = 0;
		for (var i = 0; i < cards.length; i++) {
			sum += cards[i].value;
		}
		if (sum > 21) {
			//change aces' value from 11 to 1
			for (var i = 0; i < cards.length; i++) {
				if (cards[i].value === 11) {
					cards[i].value = 1;
					break;
				}
			}
			//all aces have been changed, sum stands.
			if (i === cards.length)
				finished = true;
		}
		else finished = true;
	}
	return sum;
}

//intro screen
this.$intro = function() {

	var credits = "\n" + expandMissionText("hoopy-credits")+formatCredits(player.credits, true, true);

	//gambling choices
	var options = {
		"1_EXIT" : "Exit"
	};
	if (player.credits >= 10)
		options["2_10"] = "Bet " + formatCredits(10, true, true);
	else credits += expandMissionText("hoopy-no-credit");
	if (player.credits >= 100)
		options["3_50"] = "Bet " + formatCredits(50, true, true);
	if (player.credits >= 500)
		options["4_100"] = "Bet " + formatCredits(100, true, true);	
	
	mission.runScreen({
		titleKey: "hoopy-blackjack-title",
		message: expandMissionText("hoopy-blackjack-intro-story") + credits,
		model: "hoopy_casino_blackjack_card_intro",
		background: "hoopy_table_bg.png",
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
	function (choice) {
		if (choice === "2_10") this.$playGame(10);
		else if (choice === "3_50") this.$playGame(50);
		else if (choice === "4_100") this.$playGame(100);
	});
}

//first pay, then deal
this.$playGame = function(bet) {
	
	//pay up first
	player.credits -= bet;
	this.$bet = bet;//initial bet
	this.$totalBet = bet;//sum of all bets in round
	
	//init a new deck
	this.$playDeck = this.$virginDeck();
	
	//dealer initial hand
	var dealerHand = new Object();
	dealerHand.cards = [this.$drawCard(), this.$drawCard()];
	dealerHand.cards[1].hide = 1;
	this.$dealerHands = [dealerHand];
	
	//player initial hand
	var playerHand = new Object();
	playerHand.cards = [this.$drawCard(), this.$drawCard()];
	playerHand.bet = bet;
	this.$playerHands = [playerHand];

	//lets play some blackjack
	this.$deal(0);
}

this.$updateHandProps = function(hand, hands) {
	hand.value = this.$calculateHandValue(hand.cards);
	if (hand.value === 21) {
		if (hands.length === 1 && hand.cards.length === 2) {
			hand.status = "blackjack";
		}
		else hand.status = "21";
	}
	else if (hand.value > 21) hand.status = "busted";
	else if (hand.status !== "stand") hand.status = "hit";
}

//Deal
this.$deal = function() {
	
	//rotate till playable hand
	for (var hand = 0; hand < this.$playerHands.length; hand++) {
		var playerHand = this.$playerHands[hand];
		this.$updateHandProps(playerHand, this.$playerHands);
		if (playerHand.value < 21 && playerHand.status !== "stand")
			break;
	}
	
	//dealer's turn?
	if (hand === this.$playerHands.length) {
		this.$resolve();
		return;
	}
	
	//choices
	var options = {};
	if (playerHand.status === "hit") {
		options["1_HIT"] = "Hit";
		options["2_STAND"] = "Stand";
	}
	if (playerHand.cards.length === 2 && playerHand.status === "hit" && player.credits >= this.$bet) {
		options["3_DOUBLE"] = "Double Down ("+formatCredits(this.$bet, true, true)+")";
	}
	if (playerHand.cards.length === 2 && (playerHand.cards[0].value === playerHand.cards[1].value || playerHand.cards[0].rank === playerHand.cards[1].rank) && this.$playerHands.length < 4) {
		options["4_SPLIT"] = "Split ("+formatCredits(this.$bet, true, true)+")";
	}
	if (playerHand.cards.length === 2 && this.$playerHands.length === 1) {
		options["5_SURRENDER"] = "Surrender";
	}

	//status message
	var message = "Player hand: " + playerHand.value + "\n\n";
	message += "Total bet: " + formatCredits(this.$totalBet, true, true);
	message += "\nCredits: " + formatCredits(player.credits, true, true);

	mission.runScreen({
		titleKey: "hoopy-blackjack-title",
		model: "hoopy_casino_blackjack_card_base",
		background: "hoopy_table_bg.png",
		message: message,
		spinModel: false,
		choices: options,
	},
	function (choice) {
		if (choice === "1_HIT") {
			playerHand.cards.push(this.$drawCard());
			this.$deal();
			return;
		}
		else if (choice === "2_STAND") {
			playerHand.status = "stand";
			this.$deal();
			return;
		}
		else if (choice === "3_DOUBLE") {
			playerHand.cards.push(this.$drawCard());
			this.$updateHandProps(playerHand, this.$playerHands);
			if (playerHand.value < 21) playerHand.status = "stand";
			player.credits -= this.$bet;
			this.$totalBet += this.$bet;
			playerHand.bet = 2 * playerHand.bet;
			this.$deal();
			return;
		}
		else if (choice === "4_SPLIT") {
			
			//limit to one card after splitting aces!!!!!!!
			if (playerHand.cards[0].rank === 1) {
				playerHand.cards[0].value = 11;
				playerHand.cards[1].value = 11;
			}
			player.credits -= this.$bet;
			this.$totalBet += this.$bet;
			var newHand = new Object();
			newHand.cards = [playerHand.cards.pop(), this.$drawCard()];
			newHand.bet = this.$bet;
			this.$playerHands.push(newHand);
			playerHand.cards.push(this.$drawCard());
			this.$deal();
			return;
		}
		else if (choice === "5_SURRENDER") {
			playerHand.status = "surrender";
			this.$resolve();
			return;
		}
		else {
			this.$intro();
			return;
		}
	}
	);
	
	this.$updateScreen();
	
	//update flasher markers
	//while playing: yellow - current hand, red - busted hand
	for (var i = 0; i < this.$playerHands.length; i++) {
		var status = this.$playerHands[i].status;
		if (i === hand)
			mission.displayModel.flashers[i].color = "yellowColor";
		else if (status === "busted")
			mission.displayModel.flashers[i].color = "redColor";
		else {
			mission.displayModel.flashers[i].position = [0, 0, 50];
		}
	}
	for (var j = i; j < 4; j++)
		mission.displayModel.flashers[j].position = [0, 0, 50];
}

this.$resolve = function() {

	var dealerHand = this.$dealerHands[0];
	this.$updateHandProps(dealerHand, this.$dealerHands);
	dealerHand.cards[1].hide = false;

	//check player for non-busted hands
	var busted = true;
	for (var i = 0; i < this.$playerHands.length; i++) {
		if (this.$playerHands[i].status !== "busted") {
			busted = false;
			break;
		}
	}

	//if all player cards are busted, dealer automatically wins
	if (busted || this.$playerHands[i].status === "surrender") {
		for (var i = 0; i < this.$playerHands.length; i++) {
			this.$playerHands[i].result = "loss";
		}
	}
	else {
		//start drawing cards until we go over 16.
		while (dealerHand.value < 17) {
			dealerHand.cards.push(this.$drawCard());
			this.$updateHandProps(dealerHand, this.$dealerHands);
		}
		//compare player hands to the dealer hand
		for (var i = 0; i < this.$playerHands.length; i++) {
			var playerHand = this.$playerHands[i];
			//if the player has not busted, we'll compare
			if (playerHand.status !== "busted") {
				//blackjack
				if (playerHand.status === "blackjack") {
					if (dealerHand.status === "blackjack")
						playerHand.result = "push";
					else playerHand.result = "win";
				}
				//push
				else if (dealerHand.value === playerHand.value)
					playerHand.result = "push";
				//win
				else if (dealerHand.value > 21 || (21 - playerHand.value < 21 - dealerHand.value))
					playerHand.result = "win";
				//loss
				else playerHand.result = "loss";
			}
			//if the player has busted, it's a loss
			else playerHand.result = "loss";
		}
	}

	//calculate the winnings
	var win = 0;
	for (var i = 0; i < this.$playerHands.length; i++) {
		var playerHand = this.$playerHands[i];
		if (playerHand.result === "win") {
			if (playerHand.status === "blackjack")
				win += 2.5 * playerHand.bet;
			else win += 2 * playerHand.bet;
		}
		else if (playerHand.result === "push")
			win += playerHand.bet;
		else if (playerHand.status === "surrender" && dealerHand.status !== "blackjack")
			win += playerHand.bet / 2;
	}
	player.credits += win;
	
	//status message
	var resultMessage = "";
	
	//player
	for (var i = 0; i < this.$playerHands.length; i++) {
		var playerHand = this.$playerHands[i]
		resultMessage += "Player hand: ";
		if (playerHand.status === "blackjack")
			resultMessage += "Blackjack\n";
		else if (playerHand.status === "busted")
			resultMessage += "Busted\n";
		else if (playerHand.result === "push")
			resultMessage += "Push\n";
		else if (playerHand.status === "surrender")
			resultMessage += "Surrender\n";
		else resultMessage += playerHand.value + "\n";
	}
	
	//dealer
	if (dealerHand.status === "blackjack")
		resultMessage += "Dealer hand: Blackjack\n\n"
	else if (dealerHand.status === "busted")
		resultMessage += "Dealer hand: Busted\n\n"
	else resultMessage += "Dealer hand: " + dealerHand.value + "\n\n";

	//winnings
	if (win - this.$totalBet> 0)
		resultMessage += "You win " + formatCredits(win -  this.$totalBet, true, true) + "\n";
	else if (win - this.$totalBet< 0)
		resultMessage += "You lose " + formatCredits(this.$totalBet - win, true, true) + "\n";
	else resultMessage += "You get even\n"
	
	resultMessage += "\nCredits: " + formatCredits(player.credits, true, true);
	
	var options = {
		"2_REBET" : "Change bet",
		"3_EXIT" : "Exit"
	};
	if (player.credits >= this.$bet)
		options["1_AGAIN"] = "Deal again ("+formatCredits(this.$bet, true, true)+")";

	mission.runScreen({
		titleKey: "hoopy-blackjack-title",
		model: "hoopy_casino_blackjack_card_base",
		message: resultMessage,
		spinModel: false,
		background: "hoopy_table_bg.png",
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
	function (choice) {
		if (choice === "1_AGAIN") {
			this.$playGame(this.$bet);
			return;
		}
		else if (choice === "2_REBET") {
			this.$intro();
			return;
		}
	});
	
	this.$updateScreen(-1);
	
	//red: lose
	//green: win
	//yellow: push
	for (var i = 0; i < this.$playerHands.length; i++) {
		var result = this.$playerHands[i].result;
		if (result === "win")
			mission.displayModel.flashers[i].color = "greenColor";
		else if (result === "loss")
			mission.displayModel.flashers[i].color = "redColor";
		else mission.displayModel.flashers[i].color = "yellowColor";
	}
	for (var j = i; j < 4; j++)
		mission.displayModel.flashers[j].position = [0, 0, 50];
}

//draws a card from the current deck in play
this.$drawCard = function() {
	return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}

//update textures and positions for cards
this.$updateScreen = function() {
	//player cards subents 0-10, 11-21, 22 -32, 33-43
	//dealer cards subents 44-54

	//player cards
	for (var i = 0; i < this.$playerHands.length; i++) {
		//show player hand
		var playerHand = this.$playerHands[i];
		for (var j = 0; j < playerHand.cards.length; j++) {
			var card = playerHand.cards[j];
			var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
			var place = i * 11 + j;
			mission.displayModel.subEntities[place].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
		}
		//double down
		if (playerHand.bet === 2 * this.$bet) {
			mission.displayModel.subEntities[place].orientation = [0.5, 0.5, 0.5, 0.5];
		}
		//hide non used player subents from view
		for (var k = j; k < 11; k++) this.$hideCard(i * 11 + k);
	}
	//hide non used player subents from view
	for (var k = i * 11; k < 44; k++) this.$hideCard(k);
	
	//dealer cards
	var dealerHand = this.$dealerHands[0];
	for (var j = 0; j < dealerHand.cards.length; j++) {
		var card = dealerHand.cards[j];
		if (card.hide)
			var fileName = "casino_blackjack_card_diffuse.png";
		else
			var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
		mission.displayModel.subEntities[4 * 11 + j].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
	}
	//hide non used dealer subents from view
	for (var k = 4 * 11 + j; k < 54; k++) this.$hideCard(k);
}

//moves the cards to the centerline and turns them out of view
this.$hideCard = function(place) {
	var position = mission.displayModel.subEntities[place].position;
	position[2] = 0;
	mission.displayModel.subEntities[place].position = position;
	var orientation = [0, 0, 0, 1];
	mission.displayModel.subEntities[place].orientation = orientation;
}
Scripts/hoopy_dice.js
"use strict";

this.name = "hoopy_dice";
this.author = "spara";
this.copyright = "2014 spara";
this.license     = "CC BY-NC-SA 3.0";

//game track with bet multipliers
this.$track = [0, 0, 0, 4, 0, 8, 0, 17, 0, 35];

//add interface
this.startUpComplete = this.shipExitedWitchspace = function() {
var casinos = system.shipsWithPrimaryRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-dice",{
				title: "Smuggler's run",
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-dice-summary"),
				callback: this.$intro.bind(this)
			});
		}
	}
}

//helper function for tabulating text on screen
this.$tabulate = function(line, width) {
	var hairSpace = String.fromCharCode(31);
	var space = defaultFont.measureString(" ");
	while (defaultFont.measureString(line) < width - space)
		line += " ";
	while (defaultFont.measureString(line) < width)
		line += hairSpace;
	return line;
}

//intro screen
this.$intro = function() {
	var bets = [10, 50, 100];
	//build and format the payoff table for screen
	var payoffMessage = "Correct";
	for (var i = 0; i < 3; i++) {
		payoffMessage = this.$tabulate(payoffMessage, 5 * (i + 1));
		payoffMessage += formatCredits(bets[i], true, true);
	}
	payoffMessage = "\n\n" + payoffMessage + "\n\n";
	for (i = this.$track.length - 1; i > 0; i--) {
		if (this.$track[i] !== 0) {
			var line = i + 1;
			for (var j = 0; j < 3; j++) {
				line = this.$tabulate(line, 5 * (j + 1));
				line += this.$track[i] * bets[j];
			}
			payoffMessage += line+"\n";
		}
	}
	
	//format player credits for screen
	var credits = expandMissionText("hoopy-credits")+formatCredits(player.credits, true, true);
	
	var options = {
		"1_EXIT" : "Exit"
	};
	if (player.credits >= 10)
		options["2_10"] = "Bet 10";
	else credits += expandMissionText("hoopy-no-credit");
	if (player.credits >= 50)
		options["3_50"] = "Bet 50";
	if (player.credits >= 100)
		options["4_100"] = "Bet 100";
	mission.runScreen({
		titleKey: "hoopy-dice-title",
		message: expandMissionText("hoopy-dice-intro-story")  + payoffMessage + credits,
		choices: options,
		background: "hoopy_dice_bg-intro.png"
	},
	function (choice) {
		if (choice === "2_10") this.$playGame(10);
		else if (choice === "3_50") this.$playGame(50);
		else if (choice === "4_100") this.$playGame(100);
	}
	);
}

//da game
this.$playGame = function(bet, prevSum, round, track, select) {
	//init the game
	if (typeof round === 'undefined') {
		var round = 0;
		var track = "";
		player.credits -= bet;
	}
	
	//roll the dice
	var die1 = Math.ceil(6 * Math.random());
	var die2 = Math.ceil(6 * Math.random());
	var sum = die1 + die2;

	//check the guess
	var pass = true;
	if (typeof prevSum !== 'undefined') {
		if (select === "high_same") {
			if (sum < prevSum) 
				pass = false;
		}
		else if (select === "high") {
			if (sum <= prevSum) 
				pass = false;
		}
		else if (select === "low_same") {
			if (sum > prevSum) 
				pass = false;
		}
		else if (select === "low") {
			if (sum >= prevSum)
				pass = false;
		}
	}

//debug	
//pass = true; 

	//build the track display
	track += sum;
	if (round <= this.$track.length - 1)
		track += " > ";
	var messageTrack = track;
	for (var i = round; i < this.$track.length; i++) {
		if (this.$track[i] !== 0)
			messageTrack += formatCredits(bet * this.$track[i], false, true);
		else messageTrack += "?";
		if (i < this.$track.length - 1 )
			messageTrack += " > ";
	}
	
	//correct guess
	if (pass) {
		var options = {};
		//cash out
		if (round > 0 && this.$track[round-1] !== 0) {
			var cash_out = formatCredits(bet * this.$track[round-1], false, true);
			options["1_CASH"] = "Cash out " + cash_out;
			var message = expandMissionText("hoopy-dice-track-cash");
			var background = "hoopy_dice_bg-cash.png";
		}
		else { 
			var message = expandMissionText("hoopy-dice-track-basic");
			var background = "hoopy_dice_bg-basic.png";
		}
		//guess choices
		if (round !== this.$track.length) {
			if (sum >= 7)
				options["2_HIGH_SAME"] = "Higher or same";
			else
				options["3_HIGH"] = "Higher";
			if (sum <= 7)
				options["4_LOW_SAME"] = "Lower or same";
			else
				options["5_LOW"] = "Lower";
		}
		else 
			var message = expandMissionText("hoopy-dice-track-final");
		mission.runScreen({
			titleKey: "hoopy-dice-title",
			overlay: "hoopy_dice_"+die1+"-"+die2+".png",
			message: messageTrack + message,
			choices: options,
			background: background
		}, 
		function (choice) {
			if (choice === "1_CASH") {
				this.$cashOut(bet, round);
				return;
			}
			else if (choice === "2_HIGH_SAME") {
				this.$playGame(bet, sum, round + 1, track, "high_same");
				return;
			}
			else if (choice === "3_HIGH") {
				this.$playGame(bet, sum, round + 1, track, "high");
				return;
			}
			else if (choice === "4_LOW_SAME") {
				this.$playGame(bet, sum, round + 1, track, "low_same");
				return;
			}
			else if (choice === "5_LOW") {
				this.$playGame(bet, sum, round + 1, track, "low");
				return;
			}
		}
		);
	}
	else {
		var options = {
			"1_EXIT" : "Exit",
			"2_AGAIN" : "Play again"
		};
		mission.runScreen({
			titleKey: "hoopy-dice-title",
			overlay: "hoopy_dice_"+die1+"-"+die2+".png",
			message: messageTrack +expandMissionText("hoopy-dice-track-fail"),
			choices: options,
			background: "hoopy_dice_bg-fail.png"
		},
		function (choice) {
			if (choice === "2_AGAIN") {
				this.$intro();
				return;
			}
		}
		);
	}
}

this.$cashOut = function(bet, round) {
	var win = this.$track[round-1] * bet
	player.credits += win;
	var options = {
		"1_EXIT" : "Exit",
		"2_AGAIN" : "Play again"
	};
	mission.runScreen({
		titleKey: "hoopy-dice-title",
		message: formatCredits(win, false, true)+ expandMissionText("hoopy-dice-track-win"),
		choices: options,
		background: "hoopy_dice_bg-win.png"
	},
	function (choice) {
		if (choice === "2_AGAIN") {
			this.$intro();
			return;
		}
	}
	);
}
Scripts/hoopy_holdem.js
"use strict";

this.name = "hoopy_holdem";
this.author = "spara";
this.copyright = "2014 spara";
this.license     = "CC BY-NC-SA 4.0"; 

this.$highNames = ["Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace"];
this.$handRanks = ["High", "Pair","Two Pair","Three of a Kind","Straight","Flush","Full House","Four of a Kind","Straight Flush","Royal Flush"];

this.startUpComplete = this.shipExitedWitchspace = function() {
	var casinos = system.shipsWithPrimaryRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-holdem",{
				title: "hOopy hold'em",
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-holdem-summary"),
				callback: this.$intro.bind(this)
			});
		}
	}
	/*
	system.mainStation.setInterface("hoopy-holdem",{
		title: "Hoopy hold'em",
		category: expandMissionText("hoopy-gambling-category"),
		summary: expandMissionText("hoopy-holdem-summary"),
		callback: this.$intro.bind(this)
	});
	*/
	
}

//init a new deck
this.$virginDeck = function() {
	var deck = new Array();
	var suits = ["triangle", "crescent", "square", "star"];
	for (var i = 0; i < 4; i++) {
		for (var j = 1; j < 14; j++) {
			var card = new Object();
			card.suit = suits[i];
			card.rank = j;
			card.show = false;
			deck.push(card);
		}
	}
	return deck;
}

//draws a card from the current deck in play
this.$drawCard = function() {
	return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}

this.$intro = function() {
	var credits = expandMissionText("hoopy-credits") + formatCredits(player.credits, true, true);
	var options = {};
	options["1_EXIT"] = "Exit";
	if (player.credits >= 30)
		options["2_10"] = "Bet " + formatCredits(10, true, true);
	else credits += expandMissionText("hoopy-no-credit");
	if (player.credits >= 150)
		options["3_50"] = "Bet " + formatCredits(50, true, true);
	if (player.credits >= 300)
		options["4_100"] = "Bet " + formatCredits(100, true, true);
	
	mission.runScreen({
		titleKey: "hoopy-holdem-title",
		message: expandMissionText("hoopy-holdem-intro-story") + credits,
		model: "hoopy_casino_holdem_intro",
		background: "hoopy_table_bg.png",
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
	function (choice) {
		if (choice === "2_10") this.$play(10);
		else if (choice === "3_50") this.$play(50);
		else if (choice === "4_100") this.$play(100);
	}	
	);
}

//first pay, then deal
this.$play = function(bet) {
	player.credits -= bet;
	this.$ante = bet;
	this.$bets = 0;
	this.$playDeck = this.$virginDeck();
	this.$cards = new Array();
	for (var i = 0; i < 9; i++) this.$cards.push(this.$drawCard());
	this.$deal("deal");
}

this.$deal = function(phase) {
	var message = "Ante: " + formatCredits(this.$ante, true, true);
	if (this.$bets > 0)
		message += "\nBets: " + formatCredits(this.$bets, true, true);
	message += "\n\nCredits: " + formatCredits(player.credits, true, true);
	var options = {};
	switch(phase) {
		case "deal" :	this.$cards[7].show = true; 
						this.$cards[8].show = true;
						options["1_FLOP"] = "Play (" + formatCredits(this.$ante * 2, true, true) + ")";
						options["2_FOLD"] = "Fold";
						break;
		case "flop" :	this.$cards[2].show = true; 
						this.$cards[3].show = true;
						this.$cards[4].show = true;
						options["3_CHECK_TURN"] = "Check";
						if (player.credits >= this.$ante)
							options["4_BET_TURN"] = "Bet (" + formatCredits(this.$ante, true, true) + ")";
						break;
		case "turn" :	this.$cards[5].show = true; 
						options["5_CHECK_RIVER"] = "Check";
						if (player.credits >= this.$ante)
							options["6_BET_RIVER"] = "Bet (" + formatCredits(this.$ante, true, true) + ")";
						break;
	};
	mission.runScreen({
		titleKey: "hoopy-holdem-title",
		model: "hoopy_casino_holdem_base",
		message: message,
		background: "hoopy_table_bg.png",
		spinModel: false,
		choices: options
	},
	function(choice) {
		switch(choice) {
			case "1_FLOP" : player.credits -= 2 * this.$ante;
							this.$bets += 2 * this.$ante;
							this.$deal("flop");
							return;
			case "2_FOLD" : this.$showDown(true);
							return;
			case "3_CHECK_TURN" : 	this.$deal("turn");
									return;
			case "4_BET_TURN" : player.credits -= this.$ante;
								this.$bets += this.$ante;
								this.$deal("turn");
								return;
			case "5_CHECK_RIVER" : 	this.$showDown(false);
									return;
			case "6_BET_RIVER" : 	player.credits -= this.$ante;
									this.$bets += this.$ante;
									this.$showDown(false);
									return;
		}
	});
	this.$updateCards();
}

this.$handName = function(value, high) {
	if (value > 0)
		return this.$handRanks[value];
	else
		return this.$highNames[high - 7] + " " + this.$handRanks[0];
}

this.$formatHand = function(hand) {
	var formatted = "(";
	for (var i = 0; i < 5; i++) {
		var value = hand[0][i].value;
		if (value === 11) value = "J";
		else if (value === 12) value = "Q";
		else if (value === 13) value = "K";
		else if (value === 14 || value === 1) value = "A";
		formatted += value;
		if (i < 4) formatted += ", ";
		else formatted += ")";
	}
	return formatted;
}

this.$showDown = function(fold) {
	for (var i = 0; i < 9; i++) this.$cards[i].show = true;
	var playerHand = this.$bestHand(2);
	var dealerHand = this.$bestHand(0);
	var playerValues = "\n" + this.$formatHand(playerHand) + "\n\n";
	var dealerValues = "\n" + this.$formatHand(dealerHand) + "\n\n";
	var message = "Player: " + this.$handName(playerHand[1], playerHand[0][0].value) + playerValues;
	message += "Dealer: " + this.$handName(dealerHand[1], dealerHand[0][0].value) + dealerValues;
	
	if (fold) var result = "fold";
	else {
		var result = "push";
		if (dealerHand[1] > playerHand[1])
			result = "loss";
		else if (dealerHand[1] < playerHand[1]) {
			result = "win";
		}
		else {
			for (var i = 0; i < 5; i++) {
				if (playerHand[0][i].value > dealerHand[0][i].value) {
					result = "win";
					break;
				}
				else if (playerHand[0][i].value < dealerHand[0][i].value) {
					result = "loss";
					break;
				}
			}
		}
	}
	switch (result) {
		case "win" : 	if (playerHand[1] > 3) 
							var win = 2 * (this.$bets + this.$ante);
						else var win = this.$ante + 2 * (this.$bets);
						message += "You win " + formatCredits(win - this.$bets - this.$ante, true, true);
						player.credits += win;
						break;
		case "loss" : 	message += "Dealer wins, you lose " + formatCredits(this.$bets + this.$ante, true, true);
						break;
		case "push" : 	message += "It's a push, wagers returned.";
						player.credits += this.$bets + this.$ante;
						break;
		case "fold" :	message += "You fold and lose " + formatCredits(this.$ante, true, true);
						break;
	}
	message += "\n\nCredits: " + formatCredits(player.credits, true, true);
	var options = {};
	if (player.credits >= 3 * this.$ante)
		options["7_DEAL"] = "Deal again (" + formatCredits(this.$ante, true, true) + ")";
	options["8_BET"] = "Change ante";
	options["9_EXIT"] = "Exit";
	mission.runScreen({
		titleKey: "hoopy-holdem-title",
		model: "hoopy_casino_holdem_base",
		message: message,
		background: "hoopy_table_bg.png",
		spinModel: false,
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
	function(choice) {
		switch(choice) {
			case "7_DEAL" : this.$play(this.$ante);
							return;
			case "8_BET" : this.$intro(1);
							return;
		};
	});
	this.$updateCards();
}

this.$updateCards = function() {
	for (var i = 0; i < 9; i++) {
		var card = this.$cards[i];
		if (card.show)
			var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
		else var fileName = "casino_holdem_card_diffuse.png";
		mission.displayModel.subEntities[i].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
	}
}

this.$bestHand = function(start) {
	
	//make a new hand with new objects
	var hand = new Array();
	for (var i = start; i < start + 7; i++) {
		var suits = ["triangle", "crescent", "square", "star"];
		var card = new Object();
		card.value = this.$cards[i].rank;
		card.suit = suits.indexOf(this.$cards[i].suit);
		if (card.value === 1) card.value = 14;
		hand.push(card);
	}
	
	//order cards by suit
	hand.sort(function(a, b) {return a.suit - b.suit});

	//handle flushes first	
	if (hand[0].suit === hand[4].suit || hand[1].suit === hand[5].suit || hand[2].suit === hand[6].suit) {
		//suit of flush
		var suit = hand[2].suit;
		//remove wrong suit cards
		for (var i = 0; i < 7; i++) {
			if (hand[6 - i].suit !== suit)
				hand.splice(6 - i, 1);
		}
		//order cards by value
		hand.sort(function(a, b) {return b.value - a.value})
		//handle possible ace by duplicating to a different value
		if (hand[0].value === 14) {
			card = new Object();
			card.value = 1;
			card.suit = suit;
			hand.push(card);
		}
		//look for a straight
		var straight = -1;
		var length = 0;
		for (var i = 0; i < hand.length - 1; i++) {
			//tracking a straight
			if (hand[i].value - hand[i + 1].value === 1) length++;
			else if (hand[i].value - hand[i + 1].value != 0) length = 0;
			if (length === 4) {
				//highest straight starts from index i - 3
				straight = i - 3;
				break;
			}
		}
		//straight flush found
		if (straight > -1) {
			hand = hand.splice(straight, 5);
			//royal flush
			if (hand[0].value === 14)
				return [hand, 9];
			//straight flush
			else return [hand, 8];
		}
		//a plain flush found
		else {
			//take five most valuable cards
			hand = hand.splice(0, 5);
			return [hand, 5];
		}
	}

	//order cards by value
	hand.sort(function(a, b) {return b.value - a.value});
	
	//handle possible ace by duplicating to a different value
	if (hand[0].value === 14) {
		card = new Object();
		card.value = 1;
		card.suit = hand[0].suit;
		hand.push(card);
	}

	//look for a straight
	var straight = -1;
	var length = 0;
	for (var i = 0; i < hand.length - 1; i++) {
		//tracking a straight
		if (hand[i].value - hand[i + 1].value === 1) length++;
		else if (hand[i].value - hand[i + 1].value != 0) length = 0;
		if (length === 4) {
			//highest straight starts from index i - 3
			straight = i - 3;
			break;
		}
	}

	//straight found
	if (straight > -1) {
		hand = hand.splice(straight, 5);
		return [hand, 4];
	}
	
	//remove possible added ace. this was needed for straight search
	if (hand[0].value === 14)
		hand.pop();

	//make a new array of the cards so that cards with the same value are grouped ot sub arrays
	var grouped = new Array();
	grouped.push([hand[0]]);
	for (var i = 1; i < hand.length; i++) {
		//if there is a group for this card value, then push the card into it.
		if (hand[i].value === grouped[grouped.length - 1][0].value)
			grouped[grouped.length - 1].push(hand[i]);
		//otherwise create a new group
		else grouped.push([hand[i]]);
	}

	//sort grouped cards by group size
	grouped.sort(function(a, b) {return b.length - a.length});

	//four of a kind
	if (grouped[0].length === 4) {
		var newHand = grouped[0];
		var kicker = grouped[1][0];
		for (var i = 2; i < grouped.length; i++) {
			if (grouped[i][0] > kicker) kicker = grouped[i][0];
		}
		newHand.push(kicker);
		return [newHand, 7];
	}
	
	//three of a kind or full house
	if (grouped[0].length === 3) {
		var newHand = grouped[0];
		//full house
		if (grouped[1].length > 1) {
			newHand.push(grouped[1][0]);
			newHand.push(grouped[1][1]);
			return [newHand, 6];
		}
		//three of a kind
		else {
			newHand.push(grouped[1][0]);
			newHand.push(grouped[2][0]);
			return [newHand, 3];
		}
	}
	
	//pair or two pair
	if (grouped[0].length === 2) {
		var newHand = grouped[0];
		//two pair
		if (grouped[1].length > 1) {
			newHand.push(grouped[1][0]);
			newHand.push(grouped[1][1]);
			newHand.push(grouped[2][0]);
			return [newHand, 2];
		}
		//pair
		else {
			newHand.push(grouped[1][0]);
			newHand.push(grouped[2][0]);
			newHand.push(grouped[3][0]);
			return [newHand, 1];
		}
	}

	hand = hand.splice(0, 5);
	return [hand, 0];
}
Scripts/hoopy_hoops.js
"use strict";

this.name = "hoopy_casino";
this.author = "Paul Wilkins (updated by Eric Walch, further updated by spara)";
this.copyright = "(C) 2009 Paul Wilkins";
this.license     = "CC BY-NC-SA 3.0"; 

//add interface
this.startUpComplete = this.shipExitedWitchspace = function() {
	var casinos = system.shipsWithPrimaryRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-hoops",{
				title: expandMissionText("hoopy-hoops-title"),
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-hoops-summary"),
				callback: this.$startGambling.bind(this)
			});
		}
	}
}

//init the hoops
this.shipDockedWithStation = function (station) {
	if (player.ship.docked && station.primaryRole === 'casinoship') {
        missionVariables.hoopy_casino = 'NOT_NOW';
        this.setBoundaries();
    }
};

this.missionScreenOpportunity = function ()
{
    if (player.ship.docked && player.ship.dockedStation.primaryRole === 'casinoship') 
    {
        this.gamble();
    }
};


this.setBoundaries = function () {
        /*
        In the legacy version the random distribution was bad. One could win after analysing the odds
        during some time. This is a feature that should stay in. So we prepare the gamble table now a bit.
        */
        this.boundary1 = 1 + Math.random() - Math.random();
        this.boundary2 = 2 + Math.random() - Math.random();
        if (this.boundary1 > this.boundary2) this.boundary1 = this.boundary2;
        this.startCapital = player.credits;
};

this.$startGambling = function() {
	missionVariables.hoopy_casino = 'HOOPY_ENTER';
	this.gambleChoices('YES_HOOPY');
}

this.gamble = function () {
	/*
    if (missionVariables.hoopy_casino === 'HOOPY_REVISIT') {
        if (player.credits >= 100) {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_intro', overlay: 'hoopy_front.png', choicesKey: 'hoopy_casino_enter_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
            missionVariables.hoopy_casino = 'HOOPY_ENTER';
            return;
        }
    }*/
    if (missionVariables.hoopy_casino === 'HOOPY_GAMEON') {
        mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_choices', overlay: 'hoopy_cover.png', choicesKey: 'hoopy_casino_pick_hoop', music: "hoopy_theme.ogg"}, this.gambleChoices);
        this.hoopy_casino_hoop = Math.random() * 3;
        missionVariables.hoopy_casino = 'HOOPY_MAKE_CHOICE';
        return;
    }
    if (player.credits > this.startCapital + 2000) {
        mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_new_table', overlay: 'hoopy_front.png', choicesKey: 'hoopy_casino_new_table_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
        missionVariables.hoopy_casino = 'HOOPY_NEW_TABLE';
        this.setBoundaries();
    } else {
        if (missionVariables.hoopy_casino === 'HOOPY_WINNER') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_win', overlay: this.hoopy_casino_image, choicesKey: 'hoopy_casino_replay_winner_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
            player.credits += 100;
            missionVariables.hoopy_casino = 'HOOPY_REPLAY';
        }
        if (missionVariables.hoopy_casino === 'HOOPY_LOSER') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_loss', overlay: this.hoopy_casino_image, choicesKey: 'hoopy_casino_replay_loser_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
            player.credits -= 100;
            missionVariables.hoopy_casino = 'HOOPY_REPLAY';
        }
    }
    if (missionVariables.hoopy_casino === 'NOT_NOW') {
        delete this.hoopy_casino_hoop;
        delete this.hoopy_casino_image;
        delete missionVariables.hoopy_casino;
    }
};
this.gambleChoices = function (choice){
    if (missionVariables.hoopy_casino === 'HOOPY_ENTER') {
        if (choice === 'YES_HOOPY') {
			if (player.credits >= 100) {
				mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_desc', overlay: 'hoopy_clean.png', choicesKey: 'hoopy_casino_gamble_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
				missionVariables.hoopy_casino = 'HOOPY_GAMBLE';
			}
			else {
				missionVariables.hoopy_casino = 'HOOPY_REPLAY';
				this.gambleChoices('YES_HOOPY');
				return;
			}
        } else if (choice === 'NO_HOOPY') {
            missionVariables.hoopy_casino = 'NOT_NOW';
        }
        return;
    }
    if (missionVariables.hoopy_casino === 'HOOPY_GAMBLE') {
        if (choice === '0_HOOPY') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_desc', overlay: 'hoopy_clean.png', choicesKey: 'hoopy_casino_gamble_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
        } else if (choice === 'YES_HOOPY') {
            missionVariables.hoopy_casino = 'HOOPY_GAMEON';
        } else if (choice === 'NO_HOOPY') {
            missionVariables.hoopy_casino = 'NOT_NOW';
        }
        return;
    }
    if (missionVariables.hoopy_casino === 'HOOPY_MAKE_CHOICE') {
        missionVariables.hoopy_casino = 'HOOPY_LOSER';
        if (this.hoopy_casino_hoop < this.boundary1) {
			this.hoopy_casino_image = 'hoopy_Lwin.png';
            if (choice === 'LEFT_HOOPY') {
                missionVariables.hoopy_casino = 'HOOPY_WINNER';
            }
        }
        if (this.hoopy_casino_hoop >= this.boundary1 && this.hoopy_casino_hoop < this.boundary2) {
			this.hoopy_casino_image = 'hoopy_Cwin.png';
            if (choice === 'MIDDLE_HOOPY') {
                missionVariables.hoopy_casino = 'HOOPY_WINNER';
            }
        }
        if (this.hoopy_casino_hoop >= this.boundary2) {
			this.hoopy_casino_image = 'hoopy_Rwin.png';
            if (choice === 'RIGHT_HOOPY') {
                missionVariables.hoopy_casino = 'HOOPY_WINNER';
            }
        }
        return;
    }
    if (missionVariables.hoopy_casino === 'HOOPY_NEW_TABLE') {
        if (choice === 'NEW_TABLE_HOOPY') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_desc', overlay: 'hoopy_clean.png', choicesKey: 'hoopy_casino_gamble_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
            missionVariables.hoopy_casino = 'HOOPY_GAMBLE';
        } else if (choice === 'NO_HOOPY') {
            missionVariables.hoopy_casino = 'NOT_NOW';
        }
        return;
    }
    if (missionVariables.hoopy_casino === 'HOOPY_REPLAY') {
        if (choice === '0-WINNER_HOOPY') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_win', overlay: this.hoopy_casino_image, choicesKey: 'hoopy_casino_replay_winner_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
        }
        if (choice === '0-LOSER_HOOPY') {
			mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_loss', overlay: this.hoopy_casino_image, choicesKey: 'hoopy_casino_replay_loser_yesno', music: "hoopy_theme.ogg"}, this.gambleChoices);
        }
        if (choice === 'YES_HOOPY') {
            if (player.credits >= 100) {
                mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_again', overlay: 'hoopy_clean.png', music: "hoopy_theme.ogg"});
                missionVariables.hoopy_casino = 'HOOPY_GAMEON';
            } else {
                mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_nofunds', overlay: 'hoopy_front.png', music: "hoopy_theme.ogg"});
                missionVariables.hoopy_casino = 'NOT_NOW';
            }
        }
        if (choice === 'NO_HOOPY') {
            mission.runScreen({title: "Hoopy Casino", messageKey: 'hoopy_casino_goodbye', overlay: 'hoopy_front.png', music: "hoopy_theme.ogg"});
            missionVariables.hoopy_casino = 'NOT_NOW';
        }
	}    
};
Scripts/hoopy_poker.js
"use strict";

this.name = "hoopy_poker";
this.author = "spara";
this.copyright = "2014 spara";
this.license     = "CC BY-NC-SA 4.0"; 

this.payoffHands = ["Jacks or Better","Two Pair","Three of a Kind","Straight","Flush","Full House","Four of a Kind","Straight Flush","Royal Flush"];
this.payoffTable = [[10,20,30,40,60,90,250,500,2500],[20,40,60,80,120,180,500,1000,5000],[30,60,90,120,180,270,750,1500,7500],[40,80,120,160,240,360,1000,2000,10000],[50,100,150,200,300,450,1250,2500,40000]];

this.startUpComplete = this.shipExitedWitchspace = function() {
	var casinos = system.shipsWithPrimaryRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-poker",{
				title: "Video poker",
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-poker-summary"),
				callback: this.$intro.bind(this)
			});
		}
	}
}

//init a new deck
this.$virginDeck = function() {
	var deck = new Array();
	var suits = ["triangle", "crescent", "square", "star"];
	for (var i = 0; i < 4; i++) {
		for (var j = 1; j < 14; j++) {
			var card = new Object();
			card.suit = suits[i];
			card.rank = j;
			card.hold = 0; 
			deck.push(card);
		}
	}
	return deck;
}

//helper function for tabulating text on screen
this.$tabulate = function(line, width) {
	var hairSpace = String.fromCharCode(31);
	var space = defaultFont.measureString(" ");
	while (defaultFont.measureString(line) < width - space)
		line += " ";
	while (defaultFont.measureString(line) < width)
		line += hairSpace;
	return line;
}

//intro screen
this.$intro = function() {	
	//build and format the payoff table for screen
	var payoffMessage = this.$tabulate("Hand", 10);
	for (var i = 0; i < 5; i++) {
		payoffMessage += formatCredits(10 * (i + 1), true, true);
		payoffMessage = this.$tabulate(payoffMessage, 10 + 4 * (i + 1));
	}
	payoffMessage = "\n\n" + payoffMessage + "\n\n";
	for (i = 0; i < this.payoffHands.length; i++) {
		var line = this.payoffHands[this.payoffHands.length - i - 1];
		line = this.$tabulate(line, 10);
		for (var j = 0; j < 5; j++) {
			line = this.$tabulate(line, 10 + 4 * j);
			line += this.payoffTable[j][this.payoffHands.length - i - 1];
		}
		payoffMessage += line+"\n";
	}
	
	//format player credits for screen
	var credits = expandMissionText("hoopy-credits")+formatCredits(player.credits, true, true);
	
	//gambling choices
	var options = {
		"1_EXIT" : "Exit"
	};
	if (player.credits >= 10) {
		options["2_10"] = formatCredits(10, true, true);
	}
	else credits += expandMissionText("hoopy-no-credit");
	if (player.credits >= 20)
		options["3_20"] = formatCredits(20, true, true);
	if (player.credits >= 30)
		options["4_30"] = formatCredits(30, true, true);
	if (player.credits >= 40)
		options["5_40"] = formatCredits(40, true, true);
	if (player.credits >= 50)
		options["6_50"] = formatCredits(50, true, true);
	
	
	mission.runScreen({
		titleKey: "hoopy-poker-title",
		message: expandMissionText("hoopy-poker-intro-story") + payoffMessage + credits,
		model: "hoopy_casino_poker_card_spin",
		background: "hoopy_table_bg.png",
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
	function (choice) {
		if (choice === "2_10") this.$play(10);
		else if (choice === "3_20") this.$play(20);
		else if (choice === "4_30") this.$play(30);
		else if (choice === "5_40") this.$play(40);
		else if (choice === "6_50") this.$play(50);
	}
	);
}

//first pay, then deal
this.$play = function(bet) {
	player.credits -= bet;
	//init a new deck and draw a hand (don't show it yet)
	this.$playDeck = this.$virginDeck();
	var hand = new Array();
	for (var i = 0; i < 5; i++) hand.push(this.$drawCard());
	this.$deal(bet, hand);
}

//Deal
this.$deal = function(bet, hand, choice) {
	if (typeof choice === 'undefined') var choice = "0_HOLD";
	var options = {
		"0_HOLD" : "Hold/Cancel 1.",
		"1_HOLD" : "Hold/Cancel 2.",
		"2_HOLD" : "Hold/Cancel 3.",
		"3_HOLD" : "Hold/Cancel 4.",
		"4_HOLD" : "Hold/Cancel 5.",
		"5_DEAL" : "Draw"
	}
	mission.runScreen({
		titleKey: "hoopy-poker-title",
		messageKey: "hoopy-poker-deal-story",
		model: "hoopy_casino_poker_card_base",
		background: "hoopy_table_bg.png",
		spinModel: false,
		choices: options,
		initialChoicesKey: choice
	},
	function (choice) {
		if (choice === "0_HOLD")
			hand[0].hold = (hand[0].hold + 1) % 2;
		else if (choice === "1_HOLD")
			hand[1].hold = (hand[1].hold + 1) % 2;
		else if (choice === "2_HOLD")
			hand[2].hold = (hand[2].hold + 1) % 2;
		else if (choice === "3_HOLD")
			hand[3].hold = (hand[3].hold + 1) % 2;
		else if (choice === "4_HOLD")
			hand[4].hold = (hand[4].hold + 1) % 2;
		else if (choice === "5_DEAL") {
			this.$outCome(bet, hand);
			return;
		}
		this.$deal(bet, hand, choice);
		return;
	}
	);
	//update the cards on screen
	for (var i = 0; i < 5; i++)
		this.$changeCard(i, hand[i]);
}

//draw && outcome
this.$outCome = function(bet, hand) {
	//draw new cards
	for (var i = 0; i < 5; i++) {
		if (!hand[i].hold)
			hand[i] = this.$drawCard();
		else hand[i].hold = 0;
	}
	//check for wins
	var result = this.winCheck(hand);
	//fail
	if (result === -1) {
		var sound = "hoopy_lose.ogg";
		var resultText = expandMissionText("hoopy-poker-fail");
	}
	//win
	else {
		var win = this.payoffTable[(bet / 10 - 1)][result];
		var resultText = this.payoffHands[result] + ", you win " + formatCredits(win, false, true) + "."
		player.credits += win;
		var sound = "hoopy_win.ogg";
	}
	//format player credits for screen
	var credits = "\n" + expandMissionText("hoopy-credits")+formatCredits(player.credits, true, true) + "\nBet: " + formatCredits(bet, true, true) ;
	var options = {
		"1_EXIT" : "Exit",
		"2_AGAIN" : "Change bet",
	};
	if (player.credits >= bet) options["3_DEAL"] = "Deal again";
	mission.runScreen({
		titleKey: "hoopy-poker-title",
		message: resultText + credits,
		model: "hoopy_casino_poker_card_base",
		background: "hoopy_table_bg.png",
		spinModel: false,
		choices: options,
		music: sound,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
		function (choice) {
			if (choice === "2_AGAIN") {
				this.$intro();
				return;
			}
			else if (choice === "3_DEAL") {
				this.$play(bet);
				return;
			}
				
		}
	)
	//update the cards on screen
	for (var i = 0; i < 5; i++)
		this.$changeCard(i, hand[i]);
}

//draws a card from the current deck in play
this.$drawCard = function() {
	return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()),1)[0];
}

//update the texture and position for a card
this.$changeCard = function(place, card) {
	var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
	mission.displayModel.subEntities[place].setMaterials({"casino_poker_card_diffuse.png": {diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor"}});
	if (card.hold) {
		var position = mission.displayModel.subEntities[place].position;
		position[2] = 3;
		mission.displayModel.subEntities[place].position = position;
	}
}

//rules for a winning hand
this.winCheck = function(hand) {
	//work with a hand that has been ordered by rank
	var orderedHand = hand.concat();
	orderedHand.sort(function(a, b) {return a.rank - b.rank});
	
	//check for flush
	var suit = orderedHand[0].suit;
	var i = 0;
	var flush = false;
	for (i = 1; i < 5; i++) {
		if (orderedHand[i].suit !== suit) {
			i = -1; 
			break;
		}
	}
	//flush found
	if (i !== -1) flush = true;
	
	//check for straight
	var prevRank = orderedHand[0].rank;
	var straight = false
	for (i = 1; i < 5; i++) {
		if (orderedHand[i].rank - prevRank !== 1 && (i !== 1 || orderedHand[i].rank !== 10 || prevRank !== 1)) {
			i = -1; 
			break;
		}
		prevRank = orderedHand[i].rank;
	}

	//straight found
	if (i !== -1) straight = true;
	
	//straight flush
	if (flush && straight) {
		if (orderedHand[0].rank === 1 && orderedHand[4].rank === 13)
			return 8;//royal_flush
		else return 7;//straight_flush
	}
	
	//flush 
	if (flush) return 4;//flush"
	
	//straight
	if (straight) return 3;//straight
	
	//in the ordered list, for every adjacent two cards, check if they form a rank pair.
	prevRank = orderedHand[0].rank;
	var pairs = new Array();
	for (i = 1; i < 5; i++) {
		if (orderedHand[i].rank === prevRank) pairs.push(i);
		prevRank = orderedHand[i].rank;
	}

	//four of a kind (3 adjacent pairs)
	//full house (3 adjacent pairs)
	if (pairs.length === 3) {
		if (orderedHand[1].rank === orderedHand[2].rank && orderedHand[2].rank === orderedHand[3].rank)
			return 6;//four_of_a_kind
		else return 5;//full_house
	}

	//three of a kind (2 adjacent pairs)
	//two pair (2 adjacent pairs)
	if (pairs.length === 2) {
		if (pairs[1] - pairs[0] === 1)
			return 2;//three_of_a_kind
		else return 1;//two pair
	}
	
	//pair (jacks or better)
	if (pairs.length === 1) {
		if (orderedHand[pairs[0]].rank > 10 || orderedHand[pairs[0]].rank === 1)
			return 0;
	}
	
	return -1;
}
Scripts/hoopy_populator.js
"use strict";

this.name = "hoopy_populator";
this.author = "Paul Wilkins (updated by Eric Walch, further updated by spara)";
this.copyright = "(C) 2009 Paul Wilkins";
this.license     = "CC BY-NC-SA 3.0"; 

//add casino to system
this.systemWillPopulate = function (){
	// add in high tech level systems, but not in comunist systems. But, always in systems famous for their casinos.
	if (system.techLevel >= 10 && system.scrambledPseudoRandomNumber() > 0.55 && system.government != 4 || system.info.description.indexOf('hoopy casinos') > -1) {
		//no main station, no casinos.
		if (system.mainStation) {
			var coords = system.mainStation.position.subtract(system.mainStation.position.direction().multiply(50000));
			system.setPopulator("hoopy_casino", {
				callback: function(pos) {			
					system.addShips('casinoship', 1, pos);
				}.bind(this),
				location: "COORDINATES",
				coordinates: coords
			})
		}
	}
}