Persistence #1 featuring quill (#508)

* Add .scalafmt.conf

* Adopt quill for database access

* Removed postgresql-async
* Refactored all instances of database access
* Creating duplicate characters of the same account is no longer possible
* Rewrote large parts of LoginSessionActor

* Implement migrations

* Move overrides into subdirectory

* Make usernames case insensitive

* Use LOWER(?) comparison instead of storing lowercased username

* import scala.util.{Success, Failure}

* Add config and joda-time dependencies

* Add sbt-scalafmt

* Use defaultWithAlign scalafmt preset

* Format all

* Add scalafix

* Remove unused imports

* Don't lowercase username when inserting

* Update readme

* Listen on worldserver.Hostname address

* Remove database test on startup

It could fail when the global thread pool is busy loading zone
maps. Migrations run on the main thread and also serve the
purpose of verifying the database configuration so it's fine to
remove the test altogether.

* Refactor chat message handlers, zones

What started as a small change to how zones are stored turned
into a pretty big effort of refactoring the chat message handler.
The !hack command was removed, the /capturebase commandwas added.

* Expose db ports in docker-compose.yml

* Silence property override log

* Rework configuration

* Unify configuration using the typesafe.config library
* Add configuration option for public address
* Configuration is now loaded from application.conf rather than worldserver.ini
* Refactor PsLogin and remove unnecessary logging
* Move pslogin into net.psforever.pslogin namespace

* Fix coverage
This commit is contained in:
Jakob Gillich 2020-07-14 05:54:05 +02:00 committed by GitHub
parent 88b194fde2
commit e0defe8240
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
850 changed files with 144487 additions and 47476 deletions

3
.gitignore vendored
View file

@ -13,8 +13,7 @@ out/
project/metals.sbt project/metals.sbt
# User configs # User configs
config/worldserver.ini config/psforever.conf
pslogin/src/main/resources/user.conf
# Log files # Log files
*.log *.log

6
.scalafix.conf Normal file
View file

@ -0,0 +1,6 @@
rules = [
RemoveUnused
]
RemoveUnused.imports = true
RemoveUnused.privates = false
RemoveUnused.locals = false

3
.scalafmt.conf Normal file
View file

@ -0,0 +1,3 @@
version = 2.6.1
preset = defaultWithAlign
maxColumn = 120

View file

@ -78,7 +78,11 @@ The Login and World servers require PostgreSQL for persistence.
- Linux - [Debian](https://www.postgresql.org/download/linux/debian/) or [Ubuntu](https://www.postgresql.org/download/linux/ubuntu/) - Linux - [Debian](https://www.postgresql.org/download/linux/debian/) or [Ubuntu](https://www.postgresql.org/download/linux/ubuntu/)
- macOS - Application https://www.postgresql.org/download/ (or `brew install postgresql && brew services start postgresql`) - macOS - Application https://www.postgresql.org/download/ (or `brew install postgresql && brew services start postgresql`)
The default database is named `psforever` and the credentials are `psforever:psforever`. To change these, make a copy of [`config/worldserver.ini.dist`](config/worldserver.ini.dist) to `config/worldserver.ini` and change the corresponding fields in the database section. This database user will need ALL access to tables, sequences, and functions. The default database is named `psforever` and the credentials are
`psforever:psforever`. To change these, create a configuration file at
`config/psforever.conf`. For configuration options and their defaults, see
[`pslogin/src/main/resources/application.conf`]. This database user will need
ALL access to tables, sequences, and functions.
The permissions required can be summarized by the SQL below. The permissions required can be summarized by the SQL below.
Loading this in requires access to a graphical tool such as [pgAdmin](https://www.pgadmin.org/download/) (highly recommended) or a PostgreSQL terminal (`psql`) for advanced users. Loading this in requires access to a graphical tool such as [pgAdmin](https://www.pgadmin.org/download/) (highly recommended) or a PostgreSQL terminal (`psql`) for advanced users.
@ -95,9 +99,9 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA PUBLIC GRANT ALL ON FUNCTIONS TO psforever;
**NOTE:** applying default privileges _after_ importing the schema will not apply them to existing objects. To fix this, you must drop all objects and try again or apply permissions manually using the Query Tool / `psql`. **NOTE:** applying default privileges _after_ importing the schema will not apply them to existing objects. To fix this, you must drop all objects and try again or apply permissions manually using the Query Tool / `psql`.
Now you need to synchronize the schema. This is currently available in [`schema.sql`](schema.sql). The server will automatically apply the latest schema. Migrations can also be applied manually using
To do this right click on the psforever database -> Query Tool... -> Copy and paste / Open the `schema.sql` file into the editor -> Hit the "Play/Run" button. The schema should be loaded into the database. the [Flyway CLI](https://flywaydb.org/documentation/commandline/). Existing databases before the
Once you have the schema loaded in, the LoginServer will automatically create accounts on first login. If you'd like a nice account management interface, check out the [PSFPortal](https://github.com/psforever/PSFPortal) web interface. introduction of migrations must be baselined using the `flyway baseline` command.
### Becoming a GM ### Becoming a GM
@ -161,33 +165,6 @@ Using SBT, you can generate documentation for both the common and pslogin projec
Current documentation is available at [https://psforever.github.io/docs/master/index.html](https://psforever.github.io/docs/master/index.html) Current documentation is available at [https://psforever.github.io/docs/master/index.html](https://psforever.github.io/docs/master/index.html)
## Troubleshooting
#### Unable to initialize pscrypto
If you get an error like below
```
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
```
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
## Contributing
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
## Get in touch
- Website: http://psforever.net
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
- Join the #code channel and ask any questions you have there
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
## Tools ## Tools
### decodePackets ### decodePackets
@ -217,6 +194,33 @@ psf-decode-packets -o ./output-directory foo.gcap bar.gcap
By default, decodePackets takes in `.gcap` files, but it can also take gcapy ascii files with the By default, decodePackets takes in `.gcap` files, but it can also take gcapy ascii files with the
`-p` option. Run `psf-decode-packets --help` to get usage info. `-p` option. Run `psf-decode-packets --help` to get usage info.
## Troubleshooting
#### Unable to initialize pscrypto
If you get an error like below
```
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
```
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
## Contributing
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
## Get in touch
- Website: http://psforever.net
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
- Join the #code channel and ask any questions you have there
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
## License ## License
GNU GPLv3. See LICENSE.md for the full copy. GNU GPLv3. See LICENSE.md for the full copy.

124
build.sbt
View file

@ -4,8 +4,18 @@ lazy val commonSettings = Seq(
organization := "net.psforever", organization := "net.psforever",
version := "1.0.2-SNAPSHOT", version := "1.0.2-SNAPSHOT",
scalaVersion := "2.13.2", scalaVersion := "2.13.2",
scalacOptions := Seq("-unchecked", "-feature", "-deprecation", "-encoding", "utf8", "-language:postfixOps"), semanticdbEnabled := true,
semanticdbVersion := scalafixSemanticdb.revision,
scalacOptions := Seq(
"-unchecked",
"-feature",
"-deprecation",
"-encoding",
"utf8",
"-language:postfixOps",
"-Wunused:imports",
"-Xmacro-settings:materialize-derivations"
),
// Quiet test options // Quiet test options
// https://github.com/etorreborre/specs2/blob/8305db76c5084e4b3ce5827ce23117f6fb6beee4/common/shared/src/main/scala/org/specs2/main/Report.scala#L94 // https://github.com/etorreborre/specs2/blob/8305db76c5084e4b3ce5827ce23117f6fb6beee4/common/shared/src/main/scala/org/specs2/main/Report.scala#L94
// https://etorreborre.github.io/specs2/guide/SPECS2-2.4.17/org.specs2.guide.Runners.html // https://etorreborre.github.io/specs2/guide/SPECS2-2.4.17/org.specs2.guide.Runners.html
@ -14,22 +24,31 @@ lazy val commonSettings = Seq(
testOptions in QuietTest += Tests.Argument(TestFrameworks.ScalaTest, "-oCEHILMNOPQRX"), testOptions in QuietTest += Tests.Argument(TestFrameworks.ScalaTest, "-oCEHILMNOPQRX"),
// Trick taken from https://groups.google.com/d/msg/scala-user/mxV9ok7J_Eg/kt-LnsrD0bkJ // Trick taken from https://groups.google.com/d/msg/scala-user/mxV9ok7J_Eg/kt-LnsrD0bkJ
// scaladoc flags: https://github.com/scala/scala/blob/2.11.x/src/scaladoc/scala/tools/nsc/doc/Settings.scala // scaladoc flags: https://github.com/scala/scala/blob/2.11.x/src/scaladoc/scala/tools/nsc/doc/Settings.scala
scalacOptions in (Compile,doc) := { Seq( scalacOptions in (Compile, doc) ++= Seq(
"-groups", "-groups",
"-implicits", "-implicits",
"-doc-title", "PSF-LoginServer - ", "-doc-title",
"-doc-version", "master", "PSF-LoginServer - ",
"-doc-footer", "Copyright PSForever", "-doc-version",
"master",
"-doc-footer",
"Copyright PSForever",
// For non unidoc builds, you may need bd.getName before the template parameter // For non unidoc builds, you may need bd.getName before the template parameter
"-doc-source-url", "https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala", "-doc-source-url",
"-sourcepath", baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths "https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala",
) "-sourcepath",
}, baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths
),
classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat, classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat,
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.6.5", "com.typesafe.akka" %% "akka-actor" % "2.6.6",
"com.typesafe.akka" %% "akka-testkit" % "2.6.5" % "test", "com.typesafe.akka" %% "akka-slf4j" % "2.6.6",
"com.typesafe.akka" %% "akka-protobuf-v3" % "2.6.6",
"com.typesafe.akka" %% "akka-stream" % "2.6.6",
"com.typesafe.akka" %% "akka-testkit" % "2.6.6" % "test",
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.6",
"com.typesafe.akka" %% "akka-cluster-typed" % "2.6.6",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2", "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
"org.specs2" %% "specs2-core" % "4.9.4" % "test", "org.specs2" %% "specs2-core" % "4.9.4" % "test",
"org.scalatest" %% "scalatest" % "3.1.2" % "test", "org.scalatest" %% "scalatest" % "3.1.2" % "test",
@ -41,14 +60,20 @@ lazy val commonSettings = Seq(
"org.fusesource.jansi" % "jansi" % "1.12", "org.fusesource.jansi" % "jansi" % "1.12",
"org.scoverage" %% "scalac-scoverage-plugin" % "1.4.1", "org.scoverage" %% "scalac-scoverage-plugin" % "1.4.1",
"com.github.nscala-time" %% "nscala-time" % "2.24.0", "com.github.nscala-time" %% "nscala-time" % "2.24.0",
"com.github.postgresql-async" %% "postgresql-async" % "0.3.0",
"com.github.t3hnar" %% "scala-bcrypt" % "4.1", "com.github.t3hnar" %% "scala-bcrypt" % "4.1",
"org.ini4j" % "ini4j" % "0.5.4",
"org.scala-graph" %% "graph-core" % "1.13.1", "org.scala-graph" %% "graph-core" % "1.13.1",
"io.kamon" %% "kamon-bundle" % "2.1.0", "io.kamon" %% "kamon-bundle" % "2.1.0",
"io.kamon" %% "kamon-apm-reporter" % "2.1.0", "io.kamon" %% "kamon-apm-reporter" % "2.1.0",
"org.json4s" %% "json4s-native" % "3.6.8", "org.json4s" %% "json4s-native" % "3.6.8",
"com.typesafe.akka" %% "akka-stream" % "2.6.5" "com.typesafe.akka" %% "akka-stream" % "2.6.5",
"io.getquill" %% "quill-jasync-postgres" % "3.5.2",
"org.flywaydb" % "flyway-core" % "6.5.0",
"org.postgresql" % "postgresql" % "42.2.14",
"com.typesafe" % "config" % "1.4.0",
"com.github.pureconfig" %% "pureconfig" % "0.13.0",
"com.beachape" %% "enumeratum" % "1.6.1",
"joda-time" % "joda-time" % "2.10.6",
"commons-io" % "commons-io" % "2.6"
) )
) )
@ -61,63 +86,58 @@ lazy val pscryptoSettings = Seq(
lazy val psloginPackSettings = Seq( lazy val psloginPackSettings = Seq(
packMain := Map("ps-login" -> "PsLogin"), packMain := Map("ps-login" -> "PsLogin"),
packArchivePrefix := "pslogin", packArchivePrefix := "pslogin",
packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib", packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib", "${PROG_HOME}/config")),
"${PROG_HOME}/config")),
packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"), packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"),
packResourceDir += (baseDirectory.value / "config" -> "config"), packResourceDir += (baseDirectory.value / "config" -> "config"),
packResourceDir += (baseDirectory.value / "pslogin/src/main/resources" -> "config") packResourceDir += (baseDirectory.value / "pslogin/src/main/resources" -> "config")
) )
lazy val root = (project in file(".")). lazy val root = (project in file("."))
configs(QuietTest). .configs(QuietTest)
enablePlugins(PackPlugin). .enablePlugins(PackPlugin)
settings(commonSettings: _*). .settings(commonSettings: _*)
settings(psloginPackSettings: _*). .settings(psloginPackSettings: _*)
enablePlugins(ScalaUnidocPlugin). .enablePlugins(ScalaUnidocPlugin)
aggregate(pslogin, common). .aggregate(pslogin, common)
dependsOn(pslogin, common)
lazy val pslogin = (project in file("pslogin")). lazy val pslogin = (project in file("pslogin"))
configs(QuietTest). .configs(QuietTest)
settings(commonSettings: _*). .settings(commonSettings: _*)
settings( .settings(
name := "pslogin", name := "pslogin",
// ActorTests have specific timing requirements and will be flaky if run in parallel // ActorTests have specific timing requirements and will be flaky if run in parallel
parallelExecution in Test := false, parallelExecution in Test := false,
// TODO(chord): remove exclusion when WorldSessionActor is refactored: https://github.com/psforever/PSF-LoginServer/issues/279 // TODO(chord): remove exclusion when WorldSessionActor is refactored: https://github.com/psforever/PSF-LoginServer/issues/279
coverageExcludedPackages := "WorldSessionActor.*;zonemaps.*", coverageExcludedPackages := "net.psforever.pslogin.WorldSessionActor.*;net.psforever.pslogin.zonemaps.*",
// Copy all tests from Test -> QuietTest (we're only changing the run options) // Copy all tests from Test -> QuietTest (we're only changing the run options)
inConfig(QuietTest)(Defaults.testTasks) inConfig(QuietTest)(Defaults.testTasks)
). )
settings(pscryptoSettings: _*). .settings(pscryptoSettings: _*)
dependsOn(common) .dependsOn(common)
lazy val common = (project in file("common")). lazy val common = (project in file("common"))
configs(QuietTest). .configs(QuietTest)
settings(commonSettings: _*). .settings(commonSettings: _*)
settings( .settings(
name := "common", name := "common",
// Copy all tests from Test -> QuietTest (we're only changing the run options) // Copy all tests from Test -> QuietTest (we're only changing the run options)
inConfig(QuietTest)(Defaults.testTasks) inConfig(QuietTest)(Defaults.testTasks)
). )
settings(pscryptoSettings: _*) .settings(pscryptoSettings: _*)
lazy val decodePackets = (project in file("tools/decode-packets")). lazy val decodePackets = (project in file("tools/decode-packets"))
enablePlugins(PackPlugin). .enablePlugins(PackPlugin)
settings(commonSettings: _*). .settings(commonSettings: _*)
settings(decodePacketsPackSettings: _*). .settings(decodePacketsPackSettings: _*)
settings( .settings(
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0", "org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0",
"com.github.scopt" %% "scopt" % "4.0.0-RC2", "com.github.scopt" %% "scopt" % "4.0.0-RC2"
"commons-io" % "commons-io" % "2.6"
) )
). )
dependsOn(common) .dependsOn(common)
lazy val decodePacketsPackSettings = Seq( lazy val decodePacketsPackSettings = Seq(packMain := Map("psf-decode-packets" -> "DecodePackets"))
packMain := Map("psf-decode-packets" -> "DecodePackets"),
)
// Special test configuration for really quiet tests (used in CI) // Special test configuration for really quiet tests (used in CI)
lazy val QuietTest = config("quiet") extend(Test) lazy val QuietTest = config("quiet") extend (Test)

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
// Taken from http://code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/
package akka.actor package akka.actor
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
import akka.util.Timeout import akka.util.Timeout
import org.slf4j.MDC import org.slf4j.MDC
@ -52,7 +52,7 @@ object MDCContextAware {
* the current MDC values. Note: we MUST capture the ActorContext in order for senders * the current MDC values. Note: we MUST capture the ActorContext in order for senders
* to be correct! This was a bug from the original author. * to be correct! This was a bug from the original author.
*/ */
def !>(msg: Any)(implicit context: ActorContext) : Unit = def !>(msg: Any)(implicit context: ActorContext): Unit =
ref.tell(MdcMsg(MDC.getCopyOfContextMap, msg), context.self) ref.tell(MdcMsg(MDC.getCopyOfContextMap, msg), context.self)
/** /**

View file

@ -0,0 +1,69 @@
package akka.actor
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
import org.slf4j.MDC
import scala.concurrent.ExecutionContext
trait MDCPropagatingExecutionContext extends ExecutionContext {
// name the self-type "self" so we can refer to it inside the nested class
self =>
override def prepare(): ExecutionContext =
new ExecutionContext {
// Save the call-site MDC state
val context = MDC.getCopyOfContextMap
def execute(r: Runnable): Unit =
self.execute(new Runnable {
def run(): Unit = {
// Save the existing execution-site MDC state
val oldContext = MDC.getCopyOfContextMap
try {
// Set the call-site MDC state into the execution-site MDC
if (context != null)
MDC.setContextMap(context)
else
MDC.clear()
r.run()
} finally {
// Restore the existing execution-site MDC state
if (oldContext != null)
MDC.setContextMap(oldContext)
else
MDC.clear()
}
}
})
def reportFailure(t: Throwable): Unit = self.reportFailure(t)
}
}
object MDCPropagatingExecutionContext {
object Implicits {
// Convenience wrapper around the Scala global ExecutionContext so you can just do:
// import MDCPropagatingExecutionContext.Implicits.global
implicit lazy val global = MDCPropagatingExecutionContextWrapper(ExecutionContext.Implicits.global)
}
}
/**
* Wrapper around an existing ExecutionContext that makes it propagate MDC information.
*/
class MDCPropagatingExecutionContextWrapper(wrapped: ExecutionContext)
extends ExecutionContext
with MDCPropagatingExecutionContext {
override def execute(r: Runnable): Unit = wrapped.execute(r)
override def reportFailure(t: Throwable): Unit = wrapped.reportFailure(t)
}
object MDCPropagatingExecutionContextWrapper {
def apply(wrapped: ExecutionContext): MDCPropagatingExecutionContextWrapper = {
new MDCPropagatingExecutionContextWrapper(wrapped)
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever package net.psforever
class ObjectFinalizedException(msg : String) extends Exception(msg) class ObjectFinalizedException(msg: String) extends Exception(msg)
trait IFinalizable { trait IFinalizable {
var closed = false var closed = false
@ -11,12 +11,14 @@ trait IFinalizable {
} }
def assertNotClosed = { def assertNotClosed = {
if(closed) if (closed)
throw new ObjectFinalizedException(this.getClass.getCanonicalName + ": already finalized. Cannot interact with object") throw new ObjectFinalizedException(
this.getClass.getCanonicalName + ": already finalized. Cannot interact with object"
)
} }
override def finalize() = { override def finalize() = {
if(!closed) if (!closed)
println(this.getClass.getCanonicalName + ": class not closed. memory leaked") println(this.getClass.getCanonicalName + ": class not closed. memory leaked")
} }
} }

View file

@ -1,240 +0,0 @@
// Copyright (c) 2019 PSForever
package net.psforever.config
import org.ini4j
import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag
import scala.annotation.implicitNotFound
import scala.concurrent.duration._
import scala.collection.mutable.Map
case class ConfigValueMapper[T](name: String)(f: (String => Option[T])) {
def apply(t: String): Option[T] = f(t)
}
object ConfigValueMapper {
import scala.language.implicitConversions
implicit val toInt : ConfigValueMapper[Int] = ConfigValueMapper[Int]("toInt") { e =>
try {
Some(e.toInt)
} catch {
case e: Exception => None
}
}
// TypeTag is necessary to be able to retrieve an instance of the Enum class
// at runtime as it is usually erased at runtime. This is low cost as its only
// used during the config parsing
implicit def toEnum[E <: Enumeration#Value](implicit m: TypeTag[E]) : ConfigValueMapper[E] = ConfigValueMapper[E]("toEnum") { e =>
try {
Some(EnumReflector.withName[E](e))
} catch {
case e: Exception => None
}
}
implicit val toBool : ConfigValueMapper[Boolean] = ConfigValueMapper[Boolean]("toBool") { e =>
if (e == "yes") {
Some(true)
} else if (e == "no") {
Some(false)
} else {
None
}
}
implicit val toFloat : ConfigValueMapper[Float] = ConfigValueMapper[Float]("toFloat") { e =>
try {
Some(e.toFloat)
} catch {
case e: Exception => None
}
}
implicit val toDuration : ConfigValueMapper[Duration] = ConfigValueMapper[Duration]("toDuration") { e =>
try {
Some(Duration(e))
} catch {
case e: Exception => None
}
}
implicit val toStr : ConfigValueMapper[String] = ConfigValueMapper[String]("toString") { e =>
Some(e)
}
}
sealed trait ConfigEntry {
type Value
val key : String
val default : Value
def getType : String
val constraints : Seq[Constraint[Value]]
def read(v: String): Option[Value]
}
final case class ConfigEntryString(key: String, default : String, constraints : Constraint[String]*) extends ConfigEntry {
type Value = String
def getType = "String"
def read(v : String) = ConfigValueMapper.toStr(v)
}
final case class ConfigEntryInt(key: String, default : Int, constraints : Constraint[Int]*) extends ConfigEntry {
type Value = Int
def getType = "Int"
def read(v : String) = ConfigValueMapper.toInt(v)
}
final case class ConfigEntryBool(key: String, default : Boolean, constraints : Constraint[Boolean]*) extends ConfigEntry {
type Value = Boolean
def getType = "Bool"
def read(v : String) = ConfigValueMapper.toBool(v)
}
final case class ConfigEntryEnum[E <: Enumeration](key: String, default : E#Value)(implicit m : TypeTag[E#Value], implicit val m2 : TypeTag[E#ValueSet]) extends ConfigEntry {
type Value = E#Value
val constraints : Seq[Constraint[E#Value]] = Seq()
def getType = EnumReflector.values[E#ValueSet](m2).mkString(", ")
def read(v : String) = ConfigValueMapper.toEnum[E#Value](m)(v)
}
final case class ConfigEntryFloat(key: String, default : Float, constraints : Constraint[Float]*) extends ConfigEntry {
type Value = Float
def getType = "Float"
def read(v : String) = ConfigValueMapper.toFloat(v)
}
final case class ConfigEntryTime(key: String, default : Duration, constraints : Constraint[Duration]*) extends ConfigEntry {
type Value = Duration
def getType = "Time"
def read(v : String) = ConfigValueMapper.toDuration(v)
}
case class ConfigSection(name: String, entries: ConfigEntry*)
@implicitNotFound("Nothing was inferred")
sealed trait ConfigTypeRequired[-T]
object ConfigTypeRequired {
implicit object cfgTypeRequired extends ConfigTypeRequired[Any]
//We do not want Nothing to be inferred, so make an ambiguous implicit
implicit object `\n The Get[T] call needs a type T matching the corresponding ConfigEntry` extends ConfigTypeRequired[Nothing]
}
trait ConfigParser {
protected var config_map : Map[String, Any] = Map()
protected val config_template : Seq[ConfigSection]
// Misuse of this function can lead to run time exceptions when the types don't match
// ClassTag is needed due to type erasure on T
// https://dzone.com/articles/scala-classtag-a-simple-use-case
def Get[T : ConfigTypeRequired](key : String)(implicit m: ClassTag[T]) : T = {
config_map.get(key) match {
case Some(value : T) => value
case None =>
throw new NoSuchElementException(s"Config key '${key}' not found")
case Some(value : Any) =>
throw new ClassCastException(s"Incorrect type T = ${m.runtimeClass.getSimpleName} passed to Get[T]: needed ${value.getClass.getSimpleName}")
}
}
def Load(filename : String) : ValidationResult = {
var map : Map[String, Any] = scala.collection.mutable.Map()
LoadMap(filename, map) match {
case i : Invalid =>
i
case Valid =>
ReplaceConfig(map)
// run post-parse validation only if we successfully parsed
postParseChecks match {
case i : Invalid =>
i
case Valid =>
Valid
}
}
}
def LoadMap(filename : String, map : Map[String, Any]) : ValidationResult = {
val ini = new org.ini4j.Ini()
try {
ini.load(new java.io.File(filename))
} catch {
case e : org.ini4j.InvalidFileFormatException =>
return Invalid(e.getMessage)
case e : java.io.FileNotFoundException =>
return Invalid(e.getMessage)
}
val result : Seq[ValidationResult] = config_template.map { section =>
val sectionIni = ini.get(section.name)
if (sectionIni == null)
Seq(Invalid("section.missing", section.name))
else
section.entries.map(parseSection(sectionIni, _, map))
}.reduceLeft((x, y) => x ++ y)
val errors : Seq[Invalid] = result.collect { case iv : Invalid => iv }
if (errors.length > 0)
errors.reduceLeft((x, y) => x ++ y)
else
Valid
}
def ReplaceConfig(map : Map[String, Any]) : Unit = {
config_map = map
}
def GetRawConfig : Map[String, Any] = {
config_map
}
def FormatErrors(invalidResult : Invalid) : Seq[String] = {
var count = 0;
invalidResult.errors.map((error) => {
var message = error.message;
if (error.args.length > 0)
message += " ("+error.args(0)+")"
count += 1;
s"Error ${count}: ${message}"
});
}
protected def postParseChecks : ValidationResult = {
Valid
}
protected def parseSection(sectionIni : org.ini4j.Profile.Section, entry : ConfigEntry, map : Map[String, Any]) : ValidationResult = {
var rawValue = sectionIni.get(entry.key, 0)
val full_key : String = sectionIni.getName + "." + entry.key
val value = if (rawValue == null) {
println(s"config warning: missing key '${entry.key}', using default value '${entry.default}'")
entry.default
} else {
rawValue = rawValue.stripPrefix("\"").stripSuffix("\"")
entry.read(rawValue) match {
case Some(v) => v
case None => return Invalid(ValidationError(String.format("%s: value format error (expected: %s)", full_key, entry.getType)))
}
}
map += (full_key -> value)
ParameterValidator(entry.constraints, Some(value)) match {
case v @ Valid => v
case i @ Invalid(errors) => {
Invalid(errors.map(x => ValidationError(x.messages.map(full_key + ": " + _), x.args: _*)))
}
}
}
}

View file

@ -1,290 +0,0 @@
// Copyright (c) 2019 PSForever
// Lifted from https://raw.githubusercontent.com/playframework/playframework/2.7.x/core/play/src/main/scala/play/api/data/validation/Validation.scala
package net.psforever.config
/**
* A form constraint.
*
* @tparam T type of values handled by this constraint
* @param name the constraint name, to be displayed to final user
* @param args the message arguments, to format the constraint name
* @param f the validation function
*/
case class Constraint[-T](name: Option[String], args: Seq[Any])(f: (T => ValidationResult)) {
/**
* Run the constraint validation.
*
* @param t the value to validate
* @return the validation result
*/
def apply(t: T): ValidationResult = f(t)
}
/**
* This object provides helpers for creating `Constraint` values.
*
* For example:
* {{{
* val negative = Constraint[Int] {
* case i if i < 0 => Valid
* case _ => Invalid("Must be a negative number.")
* }
* }}}
*/
object Constraint {
/**
* Creates a new anonymous constraint from a validation function.
*
* @param f the validation function
* @return a constraint
*/
def apply[T](f: (T => ValidationResult)): Constraint[T] = apply(None, Nil)(f)
/**
* Creates a new named constraint from a validation function.
*
* @param name the constraint name
* @param args the constraint arguments, used to format the constraint name
* @param f the validation function
* @return a constraint
*/
def apply[T](name: String, args: Any*)(f: (T => ValidationResult)): Constraint[T] = apply(Some(name), args.toSeq)(f)
}
/**
* Defines a set of built-in constraints.
*/
object Constraints extends Constraints
/**
* Defines a set of built-in constraints.
*
* @define emailAddressDoc Defines an emailAddress constraint for `String` values which will validate email addresses.
*
* '''name'''[constraint.email]
* '''error'''[error.email]
*
* @define nonEmptyDoc Defines a required constraint for `String` values, i.e. one in which empty strings are invalid.
*
* '''name'''[constraint.required]
* '''error'''[error.required]
*/
trait Constraints {
private val emailRegex =
"""^[a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r
/**
* $emailAddressDoc
*/
def emailAddress(errorMessage: String = "error.email"): Constraint[String] = Constraint[String]("constraint.email") {
e =>
if (e == null) Invalid(ValidationError(errorMessage))
else if (e.trim.isEmpty) Invalid(ValidationError(errorMessage))
else
emailRegex
.findFirstMatchIn(e)
.map(_ => Valid)
.getOrElse(Invalid(ValidationError(errorMessage)))
}
/**
* $emailAddressDoc
*
*/
def emailAddress: Constraint[String] = emailAddress()
/**
* $nonEmptyDoc
*/
def nonEmpty(errorMessage: String = "error.required"): Constraint[String] =
Constraint[String]("constraint.required") { o =>
if (o == null) Invalid(ValidationError(errorMessage))
else if (o.trim.isEmpty) Invalid(ValidationError(errorMessage))
else Valid
}
/**
* $nonEmptyDoc
*
*/
def nonEmpty: Constraint[String] = nonEmpty()
/**
* Defines a minimum value for `Ordered` values, by default the value must be greater than or equal to the constraint parameter
*
* '''name'''[constraint.min(minValue)]
* '''error'''[error.min(minValue)] or [error.min.strict(minValue)]
*/
def min[T](
minValue: T,
strict: Boolean = false,
errorMessage: String = "error.min",
strictErrorMessage: String = "error.min.strict"
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.min", minValue) { o =>
(ordering.compare(o, minValue).sign, strict) match {
case (1, _) | (0, false) => Valid
case (_, false) => Invalid(ValidationError(errorMessage, minValue))
case (_, true) => Invalid(ValidationError(strictErrorMessage, minValue))
}
}
/**
* Defines a maximum value for `Ordered` values, by default the value must be less than or equal to the constraint parameter
*
* '''name'''[constraint.max(maxValue)]
* '''error'''[error.max(maxValue)] or [error.max.strict(maxValue)]
*/
def max[T](
maxValue: T,
strict: Boolean = false,
errorMessage: String = "error.max",
strictErrorMessage: String = "error.max.strict"
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.max", maxValue) { o =>
(ordering.compare(o, maxValue).sign, strict) match {
case (-1, _) | (0, false) => Valid
case (_, false) => Invalid(ValidationError(errorMessage, maxValue))
case (_, true) => Invalid(ValidationError(strictErrorMessage, maxValue))
}
}
/**
* Defines a minimum length constraint for `String` values, i.e. the strings length must be greater than or equal to the constraint parameter
*
* '''name'''[constraint.minLength(length)]
* '''error'''[error.minLength(length)]
*/
def minLength(length: Int, errorMessage: String = "error.minLength"): Constraint[String] =
Constraint[String]("constraint.minLength", length) { o =>
require(length >= 0, "string minLength must not be negative")
if (o == null) Invalid(ValidationError(errorMessage, length))
else if (o.size >= length) Valid
else Invalid(ValidationError(errorMessage, length))
}
/**
* Defines a maximum length constraint for `String` values, i.e. the strings length must be less than or equal to the constraint parameter
*
* '''name'''[constraint.maxLength(length)]
* '''error'''[error.maxLength(length)]
*/
def maxLength(length: Int, errorMessage: String = "error.maxLength"): Constraint[String] =
Constraint[String]("constraint.maxLength", length) { o =>
require(length >= 0, "string maxLength must not be negative")
if (o == null) Invalid(ValidationError(errorMessage, length))
else if (o.size <= length) Valid
else Invalid(ValidationError(errorMessage, length))
}
/**
* Defines a regular expression constraint for `String` values, i.e. the string must match the regular expression pattern
*
* '''name'''[constraint.pattern(regex)] or defined by the name parameter.
* '''error'''[error.pattern(regex)] or defined by the error parameter.
*/
def pattern(
regex: => scala.util.matching.Regex,
name: String = "constraint.pattern",
error: String = "error.pattern"
): Constraint[String] = Constraint[String](name, () => regex) { o =>
require(regex != null, "regex must not be null")
require(name != null, "name must not be null")
require(error != null, "error must not be null")
if (o == null) Invalid(ValidationError(error, regex))
else regex.unapplySeq(o).map(_ => Valid).getOrElse(Invalid(ValidationError(error, name)))
}
}
/**
* A validation result.
*/
sealed trait ValidationResult
/**
* Validation was a success.
*/
case object Valid extends ValidationResult
/**
* Validation was a failure.
*
* @param errors the resulting errors
*/
case class Invalid(errors: Seq[ValidationError]) extends ValidationResult {
/**
* Combines these validation errors with another validation failure.
*
* @param other validation failure
* @return a new merged `Invalid`
*/
def ++(other: Invalid): Invalid = Invalid(this.errors ++ other.errors)
}
/**
* This object provides helper methods to construct `Invalid` values.
*/
object Invalid {
/**
* Creates an `Invalid` value with a single error.
*
* @param error the validation error
* @return an `Invalid` value
*/
def apply(error: ValidationError): Invalid = Invalid(Seq(error))
/**
* Creates an `Invalid` value with a single error.
*
* @param error the validation error message
* @param args the validation error message arguments
* @return an `Invalid` value
*/
def apply(error: String, args: Any*): Invalid = Invalid(Seq(ValidationError(error, args: _*)))
}
object ParameterValidator {
def apply[T](constraints: Iterable[Constraint[T]], optionalParam: Option[T]*) =
optionalParam.flatMap {
_.map { param =>
constraints.flatMap {
_(param) match {
case i: Invalid => Some(i)
case _ => None
}
}
}
}.flatten match {
case Nil => Valid
case invalids =>
invalids.reduceLeft { (a, b) =>
a ++ b
}
}
}
/**
* A validation error.
*
* @param messages the error message, if more then one message is passed it will use the last one
* @param args the error message arguments
*/
case class ValidationError(messages: Seq[String], args: Any*) {
lazy val message = messages.last
}
object ValidationError {
def apply(message: String, args: Any*) = new ValidationError(Seq(message), args: _*)
}

View file

@ -1,54 +0,0 @@
// Copyright (c) 2019 PSForever
package net.psforever.config
import scala.reflect.runtime.universe._
/**
* Scala [[Enumeration]] helpers implementing Scala versions of
* Java's [[java.lang.Enum.valueOf(Class[Enum], String)]].
* @author Dmitriy Yefremov (http://yefremov.net/blog/scala-enum-by-name/)
*/
object EnumReflector {
private val mirror: Mirror = runtimeMirror(getClass.getClassLoader)
/**
* Returns a value of the specified enumeration with the given name.
* @param name value name
* @tparam T enumeration type
* @return enumeration value, see [[scala.Enumeration.withName(String)]]
*/
def withName[T <: Enumeration#Value: TypeTag](name: String): T = {
typeOf[T] match {
case valueType @ TypeRef(enumType, _, _) =>
val methodSymbol = factoryMethodSymbol(enumType, "withName")
val moduleSymbol = enumType.termSymbol.asModule
reflect(moduleSymbol, methodSymbol)(name).asInstanceOf[T]
}
}
/**
* Returns the set of values of an enumeration
* @tparam T enumeration type
* @return possible enumeration values, see [[scala.Enumeration.values()]]
*/
def values[T <: Enumeration#ValueSet: TypeTag]: T = {
typeOf[T] match {
case valueType @ TypeRef(enumType, _, _) =>
val methodSymbol = factoryMethodSymbol(enumType, "values")
val moduleSymbol = enumType.termSymbol.asModule
reflect(moduleSymbol, methodSymbol)().asInstanceOf[T]
}
}
private def factoryMethodSymbol(enumType: Type, name : String): MethodSymbol = {
enumType.member(TermName(name)).asMethod
}
private def reflect(module: ModuleSymbol, method: MethodSymbol)(args: Any*): Any = {
val moduleMirror = mirror.reflectModule(module)
val instanceMirror = mirror.reflect(moduleMirror.instance)
instanceMirror.reflectMethod(method)(args:_*)
}
}

View file

@ -4,7 +4,7 @@ package net.psforever.crypto
import com.sun.jna.ptr.IntByReference import com.sun.jna.ptr.IntByReference
import net.psforever.IFinalizable import net.psforever.IFinalizable
import sna.Library import sna.Library
import com.sun.jna.{NativeLibrary, Pointer} import com.sun.jna.Pointer
import scodec.bits.ByteVector import scodec.bits.ByteVector
object CryptoInterface { object CryptoInterface {
@ -14,18 +14,18 @@ object CryptoInterface {
final val PSCRYPTO_VERSION_MINOR = 1 final val PSCRYPTO_VERSION_MINOR = 1
/** /**
NOTE: this is a single, global shared library for the entire server's crypto needs * NOTE: this is a single, global shared library for the entire server's crypto needs
*
Unfortunately, access to this object didn't used to be synchronized. I noticed that * Unfortunately, access to this object didn't used to be synchronized. I noticed that
tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on * tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on
a secret..."). This heisenbug was responsible for failed Travis test runs and developer * a secret..."). This heisenbug was responsible for failed Travis test runs and developer
issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in * issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in
pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is * pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is
`jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no * `jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no
sense and after banging my head on the wall for many hours, I assumed that something deep * sense and after banging my head on the wall for many hours, I assumed that something deep
in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to * in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to
pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized. * pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized.
This *appears* to have fixed the problem. * This *appears* to have fixed the problem.
*/ */
final val psLib = new Library(libName) final val psLib = new Library(libName)
@ -51,7 +51,7 @@ object CryptoInterface {
* Used to initialize the crypto library at runtime. The version is checked and * Used to initialize the crypto library at runtime. The version is checked and
* all functions are mapped. * all functions are mapped.
*/ */
def initialize() : Unit = { def initialize(): Unit = {
// preload all library functions for speed // preload all library functions for speed
functionsList foreach psLib.prefetch functionsList foreach psLib.prefetch
@ -60,16 +60,18 @@ object CryptoInterface {
psLib.PSCrypto_Get_Version(libraryMajor, libraryMinor)[Unit] psLib.PSCrypto_Get_Version(libraryMajor, libraryMinor)[Unit]
if(!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) { if (!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) {
throw new IllegalArgumentException(s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " + throw new IllegalArgumentException(
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR") s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " +
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR"
)
} }
} }
/** /**
* Used for debugging object loading * Used for debugging object loading
*/ */
def printEnvironment() : Unit = { def printEnvironment(): Unit = {
import java.io.File import java.io.File
val classpath = System.getProperty("java.class.path") val classpath = System.getProperty("java.class.path")
@ -87,13 +89,13 @@ object CryptoInterface {
println("Required data model: " + System.getProperty("sun.arch.data.model")) println("Required data model: " + System.getProperty("sun.arch.data.model"))
} }
def MD5MAC(key : ByteVector, message : ByteVector, bytesWanted : Int) : ByteVector = { def MD5MAC(key: ByteVector, message: ByteVector, bytesWanted: Int): ByteVector = {
val out = Array.ofDim[Byte](bytesWanted) val out = Array.ofDim[Byte](bytesWanted)
// WARNING BUG: the function must be cast to something (even if void) otherwise it doesnt work // WARNING BUG: the function must be cast to something (even if void) otherwise it doesnt work
val ret = psLib.MD5_MAC(key.toArray, key.length, message.toArray, message.length, out, out.length)[Boolean] val ret = psLib.MD5_MAC(key.toArray, key.length, message.toArray, message.length, out, out.length)[Boolean]
if(!ret) if (!ret)
throw new Exception("MD5MAC failed to process") throw new Exception("MD5MAC failed to process")
ByteVector(out) ByteVector(out)
@ -106,15 +108,15 @@ object CryptoInterface {
* @param mac1 A MAC value * @param mac1 A MAC value
* @param mac2 Another MAC value * @param mac2 Another MAC value
*/ */
def verifyMAC(mac1 : ByteVector, mac2 : ByteVector) : Boolean = { def verifyMAC(mac1: ByteVector, mac2: ByteVector): Boolean = {
var okay = true var okay = true
// prevent byte by byte guessing // prevent byte by byte guessing
if(mac1.length != mac2.length) if (mac1.length != mac2.length)
return false return false
for(i <- 0 until mac1.length.toInt) { for (i <- 0 until mac1.length.toInt) {
okay = okay && mac1{i} == mac2{i} okay = okay && mac1 { i } == mac2 { i }
} }
okay okay
@ -129,17 +131,17 @@ object CryptoInterface {
val g = Array.ofDim[Byte](16) val g = Array.ofDim[Byte](16)
var dhHandle = Pointer.NULL var dhHandle = Pointer.NULL
def start(modulus : ByteVector, generator : ByteVector) : Unit = { def start(modulus: ByteVector, generator: ByteVector): Unit = {
assertNotClosed assertNotClosed
if(started) if (started)
throw new IllegalStateException("DH state has already been started") throw new IllegalStateException("DH state has already been started")
psLib.synchronized { psLib.synchronized {
dhHandle = psLib.DH_Start(modulus.toArray, generator.toArray, privateKey, publicKey)[Pointer] dhHandle = psLib.DH_Start(modulus.toArray, generator.toArray, privateKey, publicKey)[Pointer]
} }
if(dhHandle == Pointer.NULL) if (dhHandle == Pointer.NULL)
throw new Exception("DH initialization failed!") throw new Exception("DH initialization failed!")
modulus.copyToArray(p, 0) modulus.copyToArray(p, 0)
@ -148,37 +150,37 @@ object CryptoInterface {
started = true started = true
} }
def start() : Unit = { def start(): Unit = {
assertNotClosed assertNotClosed
if(started) if (started)
throw new IllegalStateException("DH state has already been started") throw new IllegalStateException("DH state has already been started")
psLib.synchronized { psLib.synchronized {
dhHandle = psLib.DH_Start_Generate(privateKey, publicKey, p, g)[Pointer] dhHandle = psLib.DH_Start_Generate(privateKey, publicKey, p, g)[Pointer]
} }
if(dhHandle == Pointer.NULL) if (dhHandle == Pointer.NULL)
throw new Exception("DH initialization failed!") throw new Exception("DH initialization failed!")
started = true started = true
} }
def agree(otherPublicKey : ByteVector) = { def agree(otherPublicKey: ByteVector) = {
if(!started) if (!started)
throw new IllegalStateException("DH state has not been started") throw new IllegalStateException("DH state has not been started")
val agreedValue = Array.ofDim[Byte](16) val agreedValue = Array.ofDim[Byte](16)
val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean] val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean]
if(!agreed) if (!agreed)
throw new Exception("Failed to DH agree") throw new Exception("Failed to DH agree")
ByteVector.view(agreedValue) ByteVector.view(agreedValue)
} }
private def checkAndReturnView(array : Array[Byte]) = { private def checkAndReturnView(array: Array[Byte]) = {
if(!started) if (!started)
throw new IllegalStateException("DH state has not been started") throw new IllegalStateException("DH state has not been started")
ByteVector.view(array) ByteVector.view(array)
@ -201,7 +203,7 @@ object CryptoInterface {
} }
override def close = { override def close = {
if(started) { if (started) {
// TODO: zero private key material // TODO: zero private key material
psLib.synchronized { psLib.synchronized {
psLib.Free_DH(dhHandle)[Unit] psLib.Free_DH(dhHandle)[Unit]
@ -213,46 +215,45 @@ object CryptoInterface {
} }
} }
class CryptoState(val decryptionKey : ByteVector, class CryptoState(val decryptionKey: ByteVector, val encryptionKey: ByteVector) extends IFinalizable {
val encryptionKey : ByteVector) extends IFinalizable {
// Note that the keys must be returned as primitive Arrays for JNA to work // Note that the keys must be returned as primitive Arrays for JNA to work
var encCryptoHandle : Pointer = Pointer.NULL var encCryptoHandle: Pointer = Pointer.NULL
var decCryptoHandle : Pointer = Pointer.NULL var decCryptoHandle: Pointer = Pointer.NULL
psLib.synchronized { psLib.synchronized {
encCryptoHandle = psLib.RC5_Init(encryptionKey.toArray, encryptionKey.length, true)[Pointer] encCryptoHandle = psLib.RC5_Init(encryptionKey.toArray, encryptionKey.length, true)[Pointer]
decCryptoHandle = psLib.RC5_Init(decryptionKey.toArray, decryptionKey.length, false)[Pointer] decCryptoHandle = psLib.RC5_Init(decryptionKey.toArray, decryptionKey.length, false)[Pointer]
} }
if(encCryptoHandle == Pointer.NULL) if (encCryptoHandle == Pointer.NULL)
throw new Exception("Encryption initialization failed!") throw new Exception("Encryption initialization failed!")
if(decCryptoHandle == Pointer.NULL) if (decCryptoHandle == Pointer.NULL)
throw new Exception("Decryption initialization failed!") throw new Exception("Decryption initialization failed!")
def encrypt(plaintext : ByteVector) : ByteVector = { def encrypt(plaintext: ByteVector): ByteVector = {
if(plaintext.length % RC5_BLOCK_SIZE != 0) if (plaintext.length % RC5_BLOCK_SIZE != 0)
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary") throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
val ciphertext = Array.ofDim[Byte](plaintext.length.toInt) val ciphertext = Array.ofDim[Byte](plaintext.length.toInt)
val ret = psLib.RC5_Encrypt(encCryptoHandle, plaintext.toArray, plaintext.length, ciphertext)[Boolean] val ret = psLib.RC5_Encrypt(encCryptoHandle, plaintext.toArray, plaintext.length, ciphertext)[Boolean]
if(!ret) if (!ret)
throw new Exception("Failed to encrypt plaintext") throw new Exception("Failed to encrypt plaintext")
ByteVector.view(ciphertext) ByteVector.view(ciphertext)
} }
def decrypt(ciphertext : ByteVector) : ByteVector = { def decrypt(ciphertext: ByteVector): ByteVector = {
if(ciphertext.length % RC5_BLOCK_SIZE != 0) if (ciphertext.length % RC5_BLOCK_SIZE != 0)
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary") throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
val plaintext = Array.ofDim[Byte](ciphertext.length.toInt) val plaintext = Array.ofDim[Byte](ciphertext.length.toInt)
val ret = psLib.RC5_Decrypt(decCryptoHandle, ciphertext.toArray, ciphertext.length, plaintext)[Boolean] val ret = psLib.RC5_Decrypt(decCryptoHandle, ciphertext.toArray, ciphertext.length, plaintext)[Boolean]
if(!ret) if (!ret)
throw new Exception("Failed to decrypt ciphertext") throw new Exception("Failed to decrypt ciphertext")
ByteVector.view(plaintext) ByteVector.view(plaintext)
@ -267,17 +268,20 @@ object CryptoInterface {
} }
} }
class CryptoStateWithMAC(decryptionKey : ByteVector, class CryptoStateWithMAC(
encryptionKey : ByteVector, decryptionKey: ByteVector,
val decryptionMACKey : ByteVector, encryptionKey: ByteVector,
val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) { val decryptionMACKey: ByteVector,
val encryptionMACKey: ByteVector
) extends CryptoState(decryptionKey, encryptionKey) {
/** /**
* Performs a MAC operation over the message. Used when encrypting packets * Performs a MAC operation over the message. Used when encrypting packets
* *
* @param message the input message * @param message the input message
* @return ByteVector * @return ByteVector
*/ */
def macForEncrypt(message : ByteVector) : ByteVector = { def macForEncrypt(message: ByteVector): ByteVector = {
MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE) MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
} }
@ -287,7 +291,7 @@ object CryptoInterface {
* @param message the input message * @param message the input message
* @return ByteVector * @return ByteVector
*/ */
def macForDecrypt(message : ByteVector) : ByteVector = { def macForDecrypt(message: ByteVector): ByteVector = {
MD5MAC(decryptionMACKey, message, MD5_MAC_SIZE) MD5MAC(decryptionMACKey, message, MD5_MAC_SIZE)
} }
@ -298,7 +302,7 @@ object CryptoInterface {
* @param message Arbitrary set of bytes * @param message Arbitrary set of bytes
* @return ByteVector * @return ByteVector
*/ */
def macAndEncrypt(message : ByteVector) : ByteVector = { def macAndEncrypt(message: ByteVector): ByteVector = {
encrypt(message) ++ MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE) encrypt(message) ++ MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
} }
} }

View file

@ -1,10 +1,11 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.newcodecs package net.psforever.newcodecs
import scodec.{ Codec, SizeBound } import scodec.Codec
import scodec.bits.BitVector import scodec.bits.BitVector
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]) extends Codec[A] { private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A])
extends Codec[A] {
private lazy val evaluatedCodec_true = codec_true private lazy val evaluatedCodec_true = codec_true
@ -26,6 +27,7 @@ private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true:
evaluatedCodec_false.decode(buffer) evaluatedCodec_false.decode(buffer)
} }
override def toString = if(choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)" override def toString =
if (choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
} }

View file

@ -4,21 +4,24 @@ package net.psforever.newcodecs
import scodec._ import scodec._
import scodec.bits.BitVector import scodec.bits.BitVector
final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None) extends Codec[Vector[A]] { final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None)
extends Codec[Vector[A]] {
def sizeBound = limit match { def sizeBound =
limit match {
case None => SizeBound.unknown case None => SizeBound.unknown
case Some(lim) => codec.sizeBound * lim.toLong case Some(lim) => codec.sizeBound * lim.toLong
} }
def encode(vector: Vector[A]) = Encoder.encodeSeq(firstCodec)(vector.slice(0,1)).map { bits => def encode(vector: Vector[A]) =
Encoder.encodeSeq(firstCodec)(vector.slice(0, 1)).map { bits =>
if (vector.length > 1) if (vector.length > 1)
bits ++ (Encoder.encodeSeq(codec)(vector.tail) getOrElse BitVector.empty) bits ++ (Encoder.encodeSeq(codec)(vector.tail) getOrElse BitVector.empty)
else else
bits bits
} }
def decode(buffer: BitVector) : scodec.Attempt[scodec.DecodeResult[Vector[A]]] = { def decode(buffer: BitVector): scodec.Attempt[scodec.DecodeResult[Vector[A]]] = {
Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match { Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match {
case Attempt.Successful(firstValue) => case Attempt.Successful(firstValue) =>
Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match { Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match {

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.newcodecs package net.psforever.newcodecs
import scodec.{ Attempt, Codec, DecodeResult, Err, SizeBound } import scodec.{Attempt, Codec, DecodeResult, Err, SizeBound}
import scodec.bits.{ BitVector, ByteOrdering } import scodec.bits.{BitVector, ByteOrdering}
final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Codec[Double] { final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Codec[Double] {
@ -14,14 +14,14 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
override def sizeBound = SizeBound.exact(bitsL) override def sizeBound = SizeBound.exact(bitsL)
def QuantizeDouble(value : Double) : Int = { def QuantizeDouble(value: Double): Int = {
val range : Double = max - min; val range: Double = max - min;
if (range == 0.0) if (range == 0.0)
return 0 return 0
val bit_max : Int = 1 << bits; val bit_max: Int = 1 << bits;
val rounded_quantized : Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt val rounded_quantized: Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt
if (rounded_quantized < 0) if (rounded_quantized < 0)
return 0 return 0
@ -32,7 +32,7 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
return rounded_quantized return rounded_quantized
} }
def UnquantizeDouble(value : Int) : Double = { def UnquantizeDouble(value: Int): Double = {
return ((max - min) * value.toDouble / (1 << bitsL.toInt).toDouble + min) return ((max - min) * value.toDouble / (1 << bitsL.toInt).toDouble + min)
} }
@ -42,7 +42,9 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
override def decode(buffer: BitVector) = { override def decode(buffer: BitVector) = {
if (buffer.sizeGreaterThanOrEqual(bitsL)) if (buffer.sizeGreaterThanOrEqual(bitsL))
Attempt.successful(DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL))) Attempt.successful(
DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL))
)
else else
Attempt.failure(Err.insufficientBits(bitsL, buffer.size)) Attempt.failure(Err.insufficientBits(bitsL, buffer.size))
} }

View file

@ -2,23 +2,28 @@
package net.psforever.newcodecs package net.psforever.newcodecs
import scodec.Attempt import scodec.Attempt
import scodec.Attempt.{Failure, Successful}
import scodec._ import scodec._
import scodec.bits.BitVector
package object newcodecs { package object newcodecs {
def q_double(min: Double, max: Double, bits: Int): Codec[Double] = new QuantizedDoubleCodec(min, max, bits) def q_double(min: Double, max: Double, bits: Int): Codec[Double] = new QuantizedDoubleCodec(min, max, bits)
def q_float(min : Double, max : Double, bits : Int): Codec[Float] = q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble) def q_float(min: Double, max: Double, bits: Int): Codec[Float] =
q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] = new BinaryChoiceCodec(choice, codec_true, codec_false) def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] =
new BinaryChoiceCodec(choice, codec_true, codec_false)
def prefixedVectorOfN[A](countCodec: Codec[Int], firstValueCodec: Codec[A], valueCodec: Codec[A]): Codec[Vector[A]] = def prefixedVectorOfN[A](countCodec: Codec[Int], firstValueCodec: Codec[A], valueCodec: Codec[A]): Codec[Vector[A]] =
countCodec. countCodec
flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }. .flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }
narrow[Vector[A]]({ case (cnt, xs) => .narrow[Vector[A]](
{
case (cnt, xs) =>
if (xs.size == cnt) Attempt.successful(xs) if (xs.size == cnt) Attempt.successful(xs)
else Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt")) else
}, xs => (xs.size, xs)). Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
withToString(s"vectorOfN($countCodec, $valueCodec)") },
xs => (xs.size, xs)
)
.withToString(s"vectorOfN($countCodec, $valueCodec)")
} }

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects package net.psforever.objects
class Account(private val accountId : Int, private val username : String, private val gm : Boolean = false) { class Account(private val accountId: Int, private val username: String, private val gm: Boolean = false) {
def AccountId : Int = accountId def AccountId: Int = accountId
def Username : String = username def Username: String = username
def GM : Boolean = gm def GM: Boolean = gm
} }

View file

@ -5,37 +5,36 @@ import net.psforever.objects.definition.AmmoBoxDefinition
import net.psforever.objects.equipment.{Ammo, Equipment} import net.psforever.objects.equipment.{Ammo, Equipment}
import net.psforever.types.PlanetSideEmpire import net.psforever.types.PlanetSideEmpire
class AmmoBox(private val ammoDef : AmmoBoxDefinition, class AmmoBox(private val ammoDef: AmmoBoxDefinition, cap: Option[Int] = None) extends Equipment {
cap : Option[Int] = None private var capacity = if (cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) }
) extends Equipment { else { FullCapacity }
private var capacity = if(cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) } else { FullCapacity }
def AmmoType : Ammo.Value = ammoDef.AmmoType def AmmoType: Ammo.Value = ammoDef.AmmoType
def Capacity : Int = capacity def Capacity: Int = capacity
def Capacity_=(toCapacity : Int) : Int = { def Capacity_=(toCapacity: Int): Int = {
capacity = AmmoBox.limitCapacity(toCapacity) capacity = AmmoBox.limitCapacity(toCapacity)
Capacity Capacity
} }
def FullCapacity : Int = ammoDef.Capacity def FullCapacity: Int = ammoDef.Capacity
def Definition : AmmoBoxDefinition = ammoDef def Definition: AmmoBoxDefinition = ammoDef
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
override def toString : String = { override def toString: String = {
AmmoBox.toString(this) AmmoBox.toString(this)
} }
} }
object AmmoBox { object AmmoBox {
def apply(ammoDef : AmmoBoxDefinition) : AmmoBox = { def apply(ammoDef: AmmoBoxDefinition): AmmoBox = {
new AmmoBox(ammoDef) new AmmoBox(ammoDef)
} }
def apply(ammoDef : AmmoBoxDefinition, capacity : Int) : AmmoBox = { def apply(ammoDef: AmmoBoxDefinition, capacity: Int): AmmoBox = {
new AmmoBox(ammoDef, Some(capacity)) new AmmoBox(ammoDef, Some(capacity))
} }
@ -48,25 +47,25 @@ object AmmoBox {
* @param box an `AmmoBox` object of unspecified capacity * @param box an `AmmoBox` object of unspecified capacity
* @return a `List` of `AmmoBox` objects with correct capacities * @return a `List` of `AmmoBox` objects with correct capacities
*/ */
def Split(box : AmmoBox) : List[AmmoBox] = { def Split(box: AmmoBox): List[AmmoBox] = {
val ammoDef = box.Definition val ammoDef = box.Definition
val boxCap : Int = box.Capacity val boxCap: Int = box.Capacity
val maxCap : Int = ammoDef.Capacity val maxCap: Int = ammoDef.Capacity
val splitCap : Int = boxCap / maxCap val splitCap: Int = boxCap / maxCap
box.Capacity = math.min(box.Capacity, maxCap) box.Capacity = math.min(box.Capacity, maxCap)
val list : List[AmmoBox] = if(splitCap == 0) { Nil } else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) } val list: List[AmmoBox] = if (splitCap == 0) { Nil }
else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) }
val leftover = boxCap - maxCap * splitCap val leftover = boxCap - maxCap * splitCap
if(leftover > 0) { if (leftover > 0) {
list :+ AmmoBox(ammoDef, leftover) list :+ AmmoBox(ammoDef, leftover)
} } else {
else {
list list
} }
} }
def limitCapacity(count : Int, min : Int = 0) : Int = math.min(math.max(min, count), 65535) def limitCapacity(count: Int, min: Int = 0): Int = math.min(math.max(min, count), 65535)
def toString(obj : AmmoBox) : String = { def toString(obj: AmmoBox): String = {
s"box of ${obj.AmmoType} ammo (${obj.Capacity})" s"box of ${obj.AmmoType} ammo (${obj.Capacity})"
} }
} }

View file

@ -10,16 +10,28 @@ import net.psforever.types._
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.collection.mutable import scala.collection.mutable
class Avatar(private val char_id : Long, val name : String, val faction : PlanetSideEmpire.Value, val sex : CharacterGender.Value, val head : Int, val voice : CharacterVoice.Value) { class Avatar(
private val char_id: Long,
val name: String,
val faction: PlanetSideEmpire.Value,
val sex: CharacterGender.Value,
val head: Int,
val voice: CharacterVoice.Value
) {
/** char_id, Character ID; a unique identifier corresponding to a database table row index */ /** char_id, Character ID; a unique identifier corresponding to a database table row index */
/** Battle Experience Points */ /** Battle Experience Points */
private var bep : Long = 0 private var bep: Long = 0
/** Command Experience Points */ /** Command Experience Points */
private var cep : Long = 0 private var cep: Long = 0
/** Cosmetics **/
private var pStyle : Option[Cosmetics] = None /** Cosmetics * */
private var pStyle: Option[Cosmetics] = None
/** Certifications */ /** Certifications */
private val certs : mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]() private val certs: mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]()
/** Implants<br> /** Implants<br>
* Unlike other objects, all `ImplantSlot` objects are already built into the `Avatar`. * Unlike other objects, all `ImplantSlot` objects are already built into the `Avatar`.
* Additionally, implants do not have tightly-coupled "`Definition` objects" that explain a formal implant object. * Additionally, implants do not have tightly-coupled "`Definition` objects" that explain a formal implant object.
@ -28,53 +40,60 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @see `ImplantSlot` * @see `ImplantSlot`
* @see `DetailedCharacterData.implants` * @see `DetailedCharacterData.implants`
*/ */
private val implants : Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot) private val implants: Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
/** Equipment Loadouts<br> /** Equipment Loadouts<br>
* 0-9 are Infantry loadouts<br> * 0-9 are Infantry loadouts<br>
* 10-14 are Vehicle loadouts * 10-14 are Vehicle loadouts
*/ */
private val equipmentLoadouts : LoadoutManager = new LoadoutManager(15) private val equipmentLoadouts: LoadoutManager = new LoadoutManager(15)
/** /**
* Squad Loadouts * Squad Loadouts
*/ */
private val squadLoadouts : LoadoutManager = new LoadoutManager(10) private val squadLoadouts: LoadoutManager = new LoadoutManager(10)
/** Locker */ /** Locker */
private val locker : LockerContainer = new LockerContainer() { private val locker: LockerContainer = new LockerContainer() {
override def toString : String = { override def toString: String = {
s"$name's ${Definition.Name}" s"$name's ${Definition.Name}"
} }
} }
private val deployables : DeployableToolbox = new DeployableToolbox private val deployables: DeployableToolbox = new DeployableToolbox
private var firstTimeEvents : List[String] = List[String]() private var firstTimeEvents: List[String] = List[String]()
/** /**
* Looking For Squad:<br> * Looking For Squad:<br>
* Indicates both a player state and the text on the marquee under the player nameplate. * Indicates both a player state and the text on the marquee under the player nameplate.
* Should only be valid when the player is not in a squad. * Should only be valid when the player is not in a squad.
*/ */
private var lfs : Boolean = false private var lfs: Boolean = false
private var vehicleOwned: Option[PlanetSideGUID] = None
private var vehicleOwned : Option[PlanetSideGUID] = None
/** key - object id<br> /** key - object id<br>
* value - time last used (ms) * value - time last used (ms)
* */ */
private var lastUsedEquipmentTimes : mutable.LongMap[Long] = mutable.LongMap[Long]() private var lastUsedEquipmentTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
/** exo-suit times are sorted by `Enumeration` order, which was determined by packet process<br> /** exo-suit times are sorted by `Enumeration` order, which was determined by packet process<br>
* key - exo-suit id<br> * key - exo-suit id<br>
* value - time last used (ms) * value - time last used (ms)
* */ */
private val lastUsedExoSuitTimes : Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L) private val lastUsedExoSuitTimes: Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L)
/** mechanized exo-suit times are sorted by subtype distinction, which was determined by packet process<br> /** mechanized exo-suit times are sorted by subtype distinction, which was determined by packet process<br>
* key - subtype id<br> * key - subtype id<br>
* value - time last used (ms) * value - time last used (ms)
* */ */
private val lastUsedMaxExoSuitTimes : Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa private val lastUsedMaxExoSuitTimes: Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa
/** key - object id<br> /** key - object id<br>
* value - time last acquired (from a terminal) (ms) * value - time last acquired (from a terminal) (ms)
* */ */
private var lastPurchaseTimes : mutable.LongMap[Long] = mutable.LongMap[Long]() private var lastPurchaseTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
/** /**
* To reload purchase and use timers, a string representing the item must be produced. * To reload purchase and use timers, a string representing the item must be produced.
* Point directly from the object id to the object definition and get the `Name` from that definition. * Point directly from the object id to the object definition and get the `Name` from that definition.
@ -83,29 +102,29 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* key - object id<br> * key - object id<br>
* value - most basic object definition information * value - most basic object definition information
*/ */
private val objectTypeNameReference : mutable.LongMap[String] = new mutable.LongMap[String]() private val objectTypeNameReference: mutable.LongMap[String] = new mutable.LongMap[String]()
def CharId : Long = char_id def CharId: Long = char_id
def BEP : Long = bep def BEP: Long = bep
def BEP_=(battleExperiencePoints : Long) : Long = { def BEP_=(battleExperiencePoints: Long): Long = {
bep = math.max(0L, math.min(battleExperiencePoints, 4294967295L)) bep = math.max(0L, math.min(battleExperiencePoints, 4294967295L))
BEP BEP
} }
def Certifications : mutable.Set[CertificationType.Value] = certs def Certifications: mutable.Set[CertificationType.Value] = certs
def CEP : Long = cep def CEP: Long = cep
def CEP_=(commandExperiencePoints : Long) : Long = { def CEP_=(commandExperiencePoints: Long): Long = {
cep = math.max(0L, math.min(commandExperiencePoints, 4294967295L)) cep = math.max(0L, math.min(commandExperiencePoints, 4294967295L))
CEP CEP
} }
def PersonalStyleFeatures : Option[Cosmetics] = pStyle def PersonalStyleFeatures: Option[Cosmetics] = pStyle
def PersonalStyleFeatures_=(app : Cosmetics) : Option[Cosmetics] = { def PersonalStyleFeatures_=(app: Cosmetics): Option[Cosmetics] = {
pStyle = Some(app) pStyle = Some(app)
pStyle pStyle
} }
@ -114,7 +133,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* Retrieve the three implant slots for this player. * Retrieve the three implant slots for this player.
* @return an `Array` of `ImplantSlot` objects * @return an `Array` of `ImplantSlot` objects
*/ */
def Implants : Array[ImplantSlot] = implants def Implants: Array[ImplantSlot] = implants
/** /**
* What kind of implant is installed into the given slot number? * What kind of implant is installed into the given slot number?
@ -122,8 +141,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param slot the slot number * @param slot the slot number
* @return the tye of implant * @return the tye of implant
*/ */
def Implant(slot : Int) : ImplantType.Value = { def Implant(slot: Int): ImplantType.Value = {
if(-1 < slot && slot < implants.length) { implants(slot).Implant } else { ImplantType.None } if (-1 < slot && slot < implants.length) { implants(slot).Implant }
else { ImplantType.None }
} }
/** /**
@ -136,8 +156,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param implant the implant being installed * @param implant the implant being installed
* @return the index of the `ImplantSlot` where the implant was installed * @return the index of the `ImplantSlot` where the implant was installed
*/ */
def InstallImplant(implant : ImplantDefinition) : Option[Int] = { def InstallImplant(implant: ImplantDefinition): Option[Int] = {
implants.find({p => p.Installed.contains(implant) || p.Implant == implant.Type}) match { //try to find the installed implant implants
.find({ p => p.Installed.contains(implant) || p.Implant == implant.Type }) match { //try to find the installed implant
case None => case None =>
recursiveFindImplantInSlot(implants.iterator, ImplantType.None) match { //install in a free slot recursiveFindImplantInSlot(implants.iterator, ImplantType.None) match { //install in a free slot
case Some(slot) => case Some(slot) =>
@ -164,7 +185,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param implantType the type of implant being uninstalled * @param implantType the type of implant being uninstalled
* @return the index of the `ImplantSlot` where the implant was found and uninstalled * @return the index of the `ImplantSlot` where the implant was found and uninstalled
*/ */
def UninstallImplant(implantType : ImplantType.Value) : Option[Int] = { def UninstallImplant(implantType: ImplantType.Value): Option[Int] = {
recursiveFindImplantInSlot(implants.iterator, implantType) match { recursiveFindImplantInSlot(implants.iterator, implantType) match {
case Some(slot) => case Some(slot) =>
implants(slot).Implant = None implants(slot).Implant = None
@ -183,22 +204,24 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param index a defaulted index value representing the structure underlying the `Iterator` param * @param index a defaulted index value representing the structure underlying the `Iterator` param
* @return the index where the target implant is installed * @return the index where the target implant is installed
*/ */
@tailrec private def recursiveFindImplantInSlot(iter : Iterator[ImplantSlot], implantType : ImplantType.Value, index : Int = 0) : Option[Int] = { @tailrec private def recursiveFindImplantInSlot(
if(!iter.hasNext) { iter: Iterator[ImplantSlot],
implantType: ImplantType.Value,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None None
} } else {
else {
val slot = iter.next val slot = iter.next
if(slot.Unlocked && slot.Implant == implantType) { if (slot.Unlocked && slot.Implant == implantType) {
Some(index) Some(index)
} } else {
else {
recursiveFindImplantInSlot(iter, implantType, index + 1) recursiveFindImplantInSlot(iter, implantType, index + 1)
} }
} }
} }
def ResetAllImplants() : Unit = { def ResetAllImplants(): Unit = {
implants.foreach(slot => { implants.foreach(slot => {
slot.Installed match { slot.Installed match {
case Some(_) => case Some(_) =>
@ -210,111 +233,110 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
}) })
} }
def EquipmentLoadouts : LoadoutManager = equipmentLoadouts def EquipmentLoadouts: LoadoutManager = equipmentLoadouts
def SquadLoadouts : LoadoutManager = squadLoadouts def SquadLoadouts: LoadoutManager = squadLoadouts
def Locker : LockerContainer = locker def Locker: LockerContainer = locker
def FifthSlot : EquipmentSlot = { def FifthSlot: EquipmentSlot = {
new OffhandEquipmentSlot(EquipmentSize.Inventory) { new OffhandEquipmentSlot(EquipmentSize.Inventory) {
val obj = new LockerEquipment(locker) val obj = new LockerEquipment(locker)
Equipment = obj Equipment = obj
} }
} }
def Deployables : DeployableToolbox = deployables def Deployables: DeployableToolbox = deployables
def FirstTimeEvents : List[String] = firstTimeEvents def FirstTimeEvents: List[String] = firstTimeEvents
def FirstTimeEvents_=(event : String) : List[String] = FirstTimeEvents_=(List(event)) def FirstTimeEvents_=(event: String): List[String] = FirstTimeEvents_=(List(event))
def FirstTimeEvents_=(events : List[String]) : List[String] = { def FirstTimeEvents_=(events: List[String]): List[String] = {
firstTimeEvents ++= events firstTimeEvents ++= events
FirstTimeEvents FirstTimeEvents
} }
def LFS : Boolean = lfs def LFS: Boolean = lfs
def LFS_=(looking : Boolean) : Boolean = { def LFS_=(looking: Boolean): Boolean = {
lfs = looking lfs = looking
LFS LFS
} }
def VehicleOwned : Option[PlanetSideGUID] = vehicleOwned def VehicleOwned: Option[PlanetSideGUID] = vehicleOwned
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleOwned_=(Some(guid)) def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
vehicleOwned = guid vehicleOwned = guid
VehicleOwned VehicleOwned
} }
def GetLastUsedTime(code : Int) : Long = { def GetLastUsedTime(code: Int): Long = {
lastUsedEquipmentTimes.get(code) match { lastUsedEquipmentTimes.get(code) match {
case Some(time) => time case Some(time) => time
case None => 0 case None => 0
} }
} }
def GetLastUsedTime(code : ExoSuitType.Value) : Long = { def GetLastUsedTime(code: ExoSuitType.Value): Long = {
lastUsedExoSuitTimes(code.id) lastUsedExoSuitTimes(code.id)
} }
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = { def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = {
if(code == ExoSuitType.MAX) { if (code == ExoSuitType.MAX) {
lastUsedMaxExoSuitTimes(subtype) lastUsedMaxExoSuitTimes(subtype)
} } else {
else {
GetLastUsedTime(code) GetLastUsedTime(code)
} }
} }
def GetAllLastUsedTimes : Map[Long, Long] = lastUsedEquipmentTimes.toMap def GetAllLastUsedTimes: Map[Long, Long] = lastUsedEquipmentTimes.toMap
def SetLastUsedTime(code : Int, time : Long) : Unit = { def SetLastUsedTime(code: Int, time: Long): Unit = {
lastUsedEquipmentTimes += code.toLong -> time lastUsedEquipmentTimes += code.toLong -> time
} }
def SetLastUsedTime(code : ExoSuitType.Value) : Unit = SetLastUsedTime(code, System.currentTimeMillis()) def SetLastUsedTime(code: ExoSuitType.Value): Unit = SetLastUsedTime(code, System.currentTimeMillis())
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = { def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = {
lastUsedExoSuitTimes(code.id) = time lastUsedExoSuitTimes(code.id) = time
} }
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = { def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit = {
if(code == ExoSuitType.MAX) { if (code == ExoSuitType.MAX) {
lastUsedMaxExoSuitTimes(subtype) = time lastUsedMaxExoSuitTimes(subtype) = time
} }
SetLastUsedTime(code, time) SetLastUsedTime(code, time)
} }
def GetLastPurchaseTime(code : Int) : Long = { def GetLastPurchaseTime(code: Int): Long = {
lastPurchaseTimes.get(code) match { lastPurchaseTimes.get(code) match {
case Some(time) => time case Some(time) => time
case None => 0 case None => 0
} }
} }
def GetAllLastPurchaseTimes : Map[Long, Long] = lastPurchaseTimes.toMap def GetAllLastPurchaseTimes: Map[Long, Long] = lastPurchaseTimes.toMap
def SetLastPurchaseTime(code : Int, time : Long) : Unit = { def SetLastPurchaseTime(code: Int, time: Long): Unit = {
lastPurchaseTimes += code.toLong -> time lastPurchaseTimes += code.toLong -> time
} }
def ObjectTypeNameReference(id : Long) : String = { def ObjectTypeNameReference(id: Long): String = {
objectTypeNameReference.get(id) match { objectTypeNameReference.get(id) match {
case Some(objectName) => objectName case Some(objectName) => objectName
case None => "" case None => ""
} }
} }
def ObjectTypeNameReference(id : Long, name : String) : String = { def ObjectTypeNameReference(id: Long, name: String): String = {
objectTypeNameReference(id) = name objectTypeNameReference(id) = name
name name
} }
def Definition : AvatarDefinition = GlobalDefinitions.avatar def Definition: AvatarDefinition = GlobalDefinitions.avatar
/* /*
Merit Commendations and Ribbons Merit Commendations and Ribbons
@ -326,7 +348,8 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
def canEqual(other: Any): Boolean = other.isInstanceOf[Avatar] def canEqual(other: Any): Boolean = other.isInstanceOf[Avatar]
override def equals(other : Any) : Boolean = other match { override def equals(other: Any): Boolean =
other match {
case that: Avatar => case that: Avatar =>
(that canEqual this) && (that canEqual this) &&
name == that.name && name == that.name &&
@ -338,7 +361,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
false false
} }
override def hashCode() : Int = { override def hashCode(): Int = {
val state = Seq(name, faction, sex, head, voice) val state = Seq(name, faction, sex, head, voice)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b) state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
} }
@ -347,9 +370,15 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
} }
object Avatar { object Avatar {
def apply(name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : CharacterVoice.Value) : Avatar = { def apply(
name: String,
faction: PlanetSideEmpire.Value,
sex: CharacterGender.Value,
head: Int,
voice: CharacterVoice.Value
): Avatar = {
new Avatar(0L, name, faction, sex, head, voice) new Avatar(0L, name, faction, sex, head, voice)
} }
def toString(avatar : Avatar) : String = s"${avatar.faction} ${avatar.name}" def toString(avatar: Avatar): String = s"${avatar.faction} ${avatar.name}"
} }

View file

@ -1,20 +1,20 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects package net.psforever.objects
class BoomerDeployable(cdef : ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) { class BoomerDeployable(cdef: ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) {
private var trigger : Option[BoomerTrigger] = None private var trigger: Option[BoomerTrigger] = None
def Trigger : Option[BoomerTrigger] = trigger def Trigger: Option[BoomerTrigger] = trigger
def Trigger_=(item : BoomerTrigger) : Option[BoomerTrigger] = { def Trigger_=(item: BoomerTrigger): Option[BoomerTrigger] = {
if(trigger.isEmpty) { //can only set trigger once if (trigger.isEmpty) { //can only set trigger once
trigger = Some(item) trigger = Some(item)
} }
Trigger Trigger
} }
def Trigger_=(item : Option[BoomerTrigger]) : Option[BoomerTrigger] = { def Trigger_=(item: Option[BoomerTrigger]): Option[BoomerTrigger] = {
if(item.isEmpty) { if (item.isEmpty) {
trigger = None trigger = None
} }
Trigger Trigger

View file

@ -5,5 +5,5 @@ import net.psforever.objects.equipment.RemoteUnit
import net.psforever.types.PlanetSideEmpire import net.psforever.types.PlanetSideEmpire
class BoomerTrigger extends SimpleItem(GlobalDefinitions.boomer_trigger) with RemoteUnit { class BoomerTrigger extends SimpleItem(GlobalDefinitions.boomer_trigger) with RemoteUnit {
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
} }

View file

@ -20,47 +20,48 @@ import net.psforever.types.CertificationType
* indicate whether the current output product is something the player is permitted to utilize. * indicate whether the current output product is something the player is permitted to utilize.
* @param cItemDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields * @param cItemDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/ */
class ConstructionItem(private val cItemDef : ConstructionItemDefinition) extends Equipment class ConstructionItem(private val cItemDef: ConstructionItemDefinition)
extends Equipment
with FireModeSwitch[ConstructionFireMode] { with FireModeSwitch[ConstructionFireMode] {
private var fireModeIndex : Int = 0 private var fireModeIndex: Int = 0
private var ammoTypeIndex : Int = 0 private var ammoTypeIndex: Int = 0
def FireModeIndex : Int = fireModeIndex def FireModeIndex: Int = fireModeIndex
def FireModeIndex_=(index : Int) : Int = { def FireModeIndex_=(index: Int): Int = {
fireModeIndex = index % Definition.Modes.length fireModeIndex = index % Definition.Modes.length
FireModeIndex FireModeIndex
} }
def FireMode : ConstructionFireMode = Definition.Modes(fireModeIndex) def FireMode: ConstructionFireMode = Definition.Modes(fireModeIndex)
def NextFireMode : ConstructionFireMode = { def NextFireMode: ConstructionFireMode = {
FireModeIndex = FireModeIndex + 1 FireModeIndex = FireModeIndex + 1
ammoTypeIndex = 0 ammoTypeIndex = 0
FireMode FireMode
} }
def AmmoTypeIndex : Int = ammoTypeIndex def AmmoTypeIndex: Int = ammoTypeIndex
def AmmoTypeIndex_=(index : Int) : Int = { def AmmoTypeIndex_=(index: Int): Int = {
ammoTypeIndex = index % FireMode.Deployables.length ammoTypeIndex = index % FireMode.Deployables.length
AmmoTypeIndex AmmoTypeIndex
} }
def AmmoType : DeployedItem.Value = FireMode.Deployables(ammoTypeIndex) def AmmoType: DeployedItem.Value = FireMode.Deployables(ammoTypeIndex)
def NextAmmoType : DeployedItem.Value = { def NextAmmoType: DeployedItem.Value = {
AmmoTypeIndex = AmmoTypeIndex + 1 AmmoTypeIndex = AmmoTypeIndex + 1
FireMode.Deployables(ammoTypeIndex) FireMode.Deployables(ammoTypeIndex)
} }
def ModePermissions : Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex) def ModePermissions: Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex)
def Definition : ConstructionItemDefinition = cItemDef def Definition: ConstructionItemDefinition = cItemDef
} }
object ConstructionItem { object ConstructionItem {
def apply(cItemDef : ConstructionItemDefinition) : ConstructionItem = { def apply(cItemDef: ConstructionItemDefinition): ConstructionItem = {
new ConstructionItem(cItemDef) new ConstructionItem(cItemDef)
} }
} }

View file

@ -5,20 +5,21 @@ object Default {
//cancellable //cancellable
import akka.actor.Cancellable import akka.actor.Cancellable
protected class InternalCancellable extends Cancellable { protected class InternalCancellable extends Cancellable {
override def cancel : Boolean = true override def cancel: Boolean = true
override def isCancelled : Boolean = true override def isCancelled: Boolean = true
} }
private val cancellable : Cancellable = new InternalCancellable private val cancellable: Cancellable = new InternalCancellable
/** /**
* Used to initialize the value of a re-usable `Cancellable` object. * Used to initialize the value of a re-usable `Cancellable` object.
* By convention, it always acts like it has been cancelled before and can be cancelled. * By convention, it always acts like it has been cancelled before and can be cancelled.
* Should be replaced with pertinent `Cancellable` logic through the initialization of an executor. * Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
*/ */
final def Cancellable : Cancellable = cancellable final def Cancellable: Cancellable = cancellable
//actor //actor
import akka.actor.{Actor => AkkaActor, ActorRef, ActorSystem, DeadLetter, Props} import akka.actor.{Actor => AkkaActor, ActorRef, ActorSystem, DeadLetter, Props}
/** /**
* An actor designed to wrap around `deadLetters` and redirect all normal messages to it. * An actor designed to wrap around `deadLetters` and redirect all normal messages to it.
* This measure is more to "protect" `deadLetters` than anything else. * This measure is more to "protect" `deadLetters` than anything else.
@ -26,22 +27,23 @@ object Default {
* The original target to which the actor is assigned will not be implicitly accredited. * The original target to which the actor is assigned will not be implicitly accredited.
*/ */
private class DefaultActor extends AkkaActor { private class DefaultActor extends AkkaActor {
def receive : Receive = { def receive: Receive = {
case msg => context.system.deadLetters ! DeadLetter(msg, sender, self) case msg => context.system.deadLetters ! DeadLetter(msg, sender, self)
} }
} }
private var defaultRef : ActorRef = ActorRef.noSender private var defaultRef: ActorRef = ActorRef.noSender
/** /**
* Instigate the default actor. * Instigate the default actor.
* @param sys the actor universe under which this default actor will exist * @param sys the actor universe under which this default actor will exist
* @return the new default actor * @return the new default actor
*/ */
def apply(sys : ActorSystem) : ActorRef = { def apply(sys: ActorSystem): ActorRef = {
if(defaultRef == ActorRef.noSender) { if (defaultRef == ActorRef.noSender) {
defaultRef = sys.actorOf(Props[DefaultActor], name = s"system-default-actor") defaultRef = sys.actorOf(Props[DefaultActor], name = s"system-default-actor")
} }
defaultRef defaultRef
} }
final def Actor : ActorRef = defaultRef final def Actor: ActorRef = defaultRef
} }

View file

@ -16,26 +16,36 @@ object Deployables {
private val log = org.log4s.getLogger("Deployables") private val log = org.log4s.getLogger("Deployables")
object Make { object Make {
def apply(item : DeployedItem.Value) : ()=>PlanetSideGameObject with Deployable = cemap(item) def apply(item: DeployedItem.Value): () => PlanetSideGameObject with Deployable = cemap(item)
private val cemap : Map[DeployedItem.Value, ()=>PlanetSideGameObject with Deployable] = Map( private val cemap: Map[DeployedItem.Value, () => PlanetSideGameObject with Deployable] = Map(
DeployedItem.boomer -> { ()=> new BoomerDeployable(GlobalDefinitions.boomer) }, DeployedItem.boomer -> { () => new BoomerDeployable(GlobalDefinitions.boomer) },
DeployedItem.he_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.he_mine) }, DeployedItem.he_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.he_mine) },
DeployedItem.jammer_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.jammer_mine) }, DeployedItem.jammer_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.jammer_mine) },
DeployedItem.spitfire_turret -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_turret) }, DeployedItem.spitfire_turret -> { () => new TurretDeployable(GlobalDefinitions.spitfire_turret) },
DeployedItem.spitfire_cloaked -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_cloaked) }, DeployedItem.spitfire_cloaked -> { () => new TurretDeployable(GlobalDefinitions.spitfire_cloaked) },
DeployedItem.spitfire_aa -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_aa) }, DeployedItem.spitfire_aa -> { () => new TurretDeployable(GlobalDefinitions.spitfire_aa) },
DeployedItem.motionalarmsensor -> { ()=> new SensorDeployable(GlobalDefinitions.motionalarmsensor) }, DeployedItem.motionalarmsensor -> { () => new SensorDeployable(GlobalDefinitions.motionalarmsensor) },
DeployedItem.sensor_shield -> { ()=> new SensorDeployable(GlobalDefinitions.sensor_shield) }, DeployedItem.sensor_shield -> { () => new SensorDeployable(GlobalDefinitions.sensor_shield) },
DeployedItem.tank_traps -> { ()=> new TrapDeployable(GlobalDefinitions.tank_traps) }, DeployedItem.tank_traps -> { () => new TrapDeployable(GlobalDefinitions.tank_traps) },
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) }, DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) }, DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret_nc -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc) }, DeployedItem.portable_manned_turret_nc -> { () =>
DeployedItem.portable_manned_turret_tr -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) }, new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc)
DeployedItem.portable_manned_turret_vs -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs) }, },
DeployedItem.deployable_shield_generator -> { ()=> new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator) }, DeployedItem.portable_manned_turret_tr -> { () =>
DeployedItem.router_telepad_deployable -> { () => new TelepadDeployable(GlobalDefinitions.router_telepad_deployable) } new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr)
).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } ) },
DeployedItem.portable_manned_turret_vs -> { () =>
new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
},
DeployedItem.deployable_shield_generator -> { () =>
new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
},
DeployedItem.router_telepad_deployable -> { () =>
new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
}
).withDefaultValue({ () => new ExplosiveDeployable(GlobalDefinitions.boomer) })
} }
/** /**
@ -60,7 +70,7 @@ object Deployables {
* @param time length of time that the deployable is allowed to exist in the game world; * @param time length of time that the deployable is allowed to exist in the game world;
* `None` indicates the normal un-owned existence time (180 seconds) * `None` indicates the normal un-owned existence time (180 seconds)
*/ */
def AnnounceDestroyDeployable(target : PlanetSideGameObject with Deployable, time : Option[FiniteDuration]) : Unit = { def AnnounceDestroyDeployable(target: PlanetSideGameObject with Deployable, time: Option[FiniteDuration]): Unit = {
val zone = target.Zone val zone = target.Zone
target.OwnerName match { target.OwnerName match {
case Some(owner) => case Some(owner) =>
@ -68,10 +78,13 @@ object Deployables {
zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target))
case None => ; case None => ;
} }
zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon( zone.LocalEvents ! LocalServiceMessage(
s"${target.Faction}",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0), PlanetSideGUID(0),
DeploymentAction.Dismiss, DeploymentAction.Dismiss,
DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))) DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))
)
) )
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone)) zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone))
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time)) zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time))
@ -86,15 +99,20 @@ object Deployables {
* @return all previously-owned deployables after they have been processed; * @return all previously-owned deployables after they have been processed;
* boomers are listed before all other deployable types * boomers are listed before all other deployable types
*/ */
def Disown(zone : Zone, avatar : Avatar, replyTo : ActorRef) : List[PlanetSideGameObject with Deployable] = { def Disown(zone: Zone, avatar: Avatar, replyTo: ActorRef): List[PlanetSideGameObject with Deployable] = {
val (boomers, deployables) = val (boomers, deployables) =
avatar.Deployables.Clear() avatar.Deployables
.Clear()
.map(zone.GUID) .map(zone.GUID)
.collect { case Some(obj) => obj.asInstanceOf[PlanetSideGameObject with Deployable] } .collect { case Some(obj) => obj.asInstanceOf[PlanetSideGameObject with Deployable] }
.partition(_.isInstanceOf[BoomerDeployable]) .partition(_.isInstanceOf[BoomerDeployable])
//do not change the OwnerName field at this time //do not change the OwnerName field at this time
boomers.collect({ case obj : BoomerDeployable => boomers.collect({
zone.LocalEvents.tell(LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))), replyTo) //near-instant case obj: BoomerDeployable =>
zone.LocalEvents.tell(
LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))),
replyTo
) //near-instant
obj.Owner = None obj.Owner = None
obj.Trigger = None obj.Trigger = None
}) })
@ -105,17 +123,17 @@ object Deployables {
boomers ++ deployables boomers ++ deployables
} }
def RemoveTelepad(vehicle: Vehicle) : Unit = { def RemoveTelepad(vehicle: Vehicle): Unit = {
val zone = vehicle.Zone val zone = vehicle.Zone
(vehicle.Utility(UtilityType.internal_router_telepad_deployable) match { (vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
case Some(util : Utility.InternalTelepad) => case Some(util: Utility.InternalTelepad) =>
val telepad = util.Telepad val telepad = util.Telepad
util.Telepad = None util.Telepad = None
zone.GUID(telepad) zone.GUID(telepad)
case _ => case _ =>
None None
}) match { }) match {
case Some(telepad : TelepadDeployable) => case Some(telepad: TelepadDeployable) =>
log.info(s"BeforeUnload: deconstructing telepad $telepad that was linked to router $vehicle ...") log.info(s"BeforeUnload: deconstructing telepad $telepad that was linked to router $vehicle ...")
telepad.Active = false telepad.Active = false
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), zone)) zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), zone))
@ -124,13 +142,11 @@ object Deployables {
} }
} }
/** /**
* Initialize the deployables backend information. * Initialize the deployables backend information.
* @param avatar the player's core * @param avatar the player's core
*/ */
def InitializeDeployableQuantities(avatar : Avatar) : Boolean = { def InitializeDeployableQuantities(avatar: Avatar): Boolean = {
log.info("Setting up combat engineering ...") log.info("Setting up combat engineering ...")
avatar.Deployables.Initialize(avatar.Certifications.toSet) avatar.Deployables.Initialize(avatar.Certifications.toSet)
} }
@ -139,7 +155,7 @@ object Deployables {
* Initialize the UI elements for deployables. * Initialize the UI elements for deployables.
* @param avatar the player's core * @param avatar the player's core
*/ */
def InitializeDeployableUIElements(avatar : Avatar) : List[(Int,Int,Int,Int)] = { def InitializeDeployableUIElements(avatar: Avatar): List[(Int, Int, Int, Int)] = {
log.info("Setting up combat engineering UI ...") log.info("Setting up combat engineering UI ...")
avatar.Deployables.UpdateUI() avatar.Deployables.UpdateUI()
} }
@ -151,7 +167,11 @@ object Deployables {
* @param certification the certification that was added * @param certification the certification that was added
* @param certificationSet all applicable certifications * @param certificationSet all applicable certifications
*/ */
def AddToDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = { def AddToDeployableQuantities(
avatar: Avatar,
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): List[(Int, Int, Int, Int)] = {
avatar.Deployables.AddToDeployableQuantities(certification, certificationSet) avatar.Deployables.AddToDeployableQuantities(certification, certificationSet)
avatar.Deployables.UpdateUI(certification) avatar.Deployables.UpdateUI(certification)
} }
@ -163,7 +183,11 @@ object Deployables {
* @param certification the certification that was added * @param certification the certification that was added
* @param certificationSet all applicable certifications * @param certificationSet all applicable certifications
*/ */
def RemoveFromDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = { def RemoveFromDeployableQuantities(
avatar: Avatar,
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): List[(Int, Int, Int, Int)] = {
avatar.Deployables.RemoveFromDeployableQuantities(certification, certificationSet) avatar.Deployables.RemoveFromDeployableQuantities(certification, certificationSet)
avatar.Deployables.UpdateUI(certification) avatar.Deployables.UpdateUI(certification)
} }

View file

@ -18,61 +18,60 @@ import services.local.{LocalAction, LocalServiceMessage}
import scala.concurrent.duration._ import scala.concurrent.duration._
class ExplosiveDeployable(cdef : ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) with JammableUnit {
with JammableUnit {
override def Definition : ExplosiveDeployableDefinition = cdef override def Definition: ExplosiveDeployableDefinition = cdef
} }
class ExplosiveDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) { class ExplosiveDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
Name = "explosive_deployable" Name = "explosive_deployable"
DeployCategory = DeployableCategory.Mines DeployCategory = DeployableCategory.Mines
Model = StandardResolutions.SimpleDeployables Model = StandardResolutions.SimpleDeployables
Packet = new SmallDeployableConverter Packet = new SmallDeployableConverter
private var detonateOnJamming : Boolean = true private var detonateOnJamming: Boolean = true
def DetonateOnJamming : Boolean = detonateOnJamming def DetonateOnJamming: Boolean = detonateOnJamming
def DetonateOnJamming_=(detonate : Boolean) : Boolean = { def DetonateOnJamming_=(detonate: Boolean): Boolean = {
detonateOnJamming = detonate detonateOnJamming = detonate
DetonateOnJamming DetonateOnJamming
} }
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor =
context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context) SimpleDeployableDefinition.SimpleUninitialize(obj, context)
} }
} }
object ExplosiveDeployableDefinition { object ExplosiveDeployableDefinition {
def apply(dtype : DeployedItem.Value) : ExplosiveDeployableDefinition = { def apply(dtype: DeployedItem.Value): ExplosiveDeployableDefinition = {
new ExplosiveDeployableDefinition(dtype.id) new ExplosiveDeployableDefinition(dtype.id)
} }
} }
class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with Damageable {
with Damageable {
def DamageableObject = mine def DamageableObject = mine
def receive : Receive = takesDamage def receive: Receive =
takesDamage
.orElse { .orElse {
case _ => ; case _ => ;
} }
protected def TakesDamage : Receive = { protected def TakesDamage: Receive = {
case Vitality.Damage(applyDamageTo) => case Vitality.Damage(applyDamageTo) =>
if(mine.CanDamage) { if (mine.CanDamage) {
val originalHealth = mine.Health val originalHealth = mine.Health
val cause = applyDamageTo(mine) val cause = applyDamageTo(mine)
val damage = originalHealth - mine.Health val damage = originalHealth - mine.Health
if(Damageable.CanDamageOrJammer(mine, damage, cause)) { if (Damageable.CanDamageOrJammer(mine, damage, cause)) {
ExplosiveDeployableControl.DamageResolution(mine, cause, damage) ExplosiveDeployableControl.DamageResolution(mine, cause, damage)
} } else {
else {
mine.Health = originalHealth mine.Health = originalHealth
} }
} }
@ -80,17 +79,18 @@ class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor
} }
object ExplosiveDeployableControl { object ExplosiveDeployableControl {
def DamageResolution(target : ExplosiveDeployable, cause : ResolvedProjectile, damage : Int) : Unit = { def DamageResolution(target: ExplosiveDeployable, cause: ResolvedProjectile, damage: Int): Unit = {
target.History(cause) target.History(cause)
if(target.Health == 0) { if (target.Health == 0) {
DestructionAwareness(target, cause) DestructionAwareness(target, cause)
} } else if (!target.Jammed && Damageable.CanJammer(target, cause)) {
else if(!target.Jammed && Damageable.CanJammer(target, cause)) { if (
if(target.Jammed = { target.Jammed = {
val radius = cause.projectile.profile.DamageRadius val radius = cause.projectile.profile.DamageRadius
Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius
}) { }
if(target.Definition.DetonateOnJamming) { ) {
if (target.Definition.DetonateOnJamming) {
val zone = target.Zone val zone = target.Zone
zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos) zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.Detonate(target.GUID, target)) zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.Detonate(target.GUID, target))
@ -105,17 +105,23 @@ object ExplosiveDeployableControl {
* @param target na * @param target na
* @param cause na * @param cause na
*/ */
def DestructionAwareness(target : ExplosiveDeployable, cause : ResolvedProjectile) : Unit = { def DestructionAwareness(target: ExplosiveDeployable, cause: ResolvedProjectile): Unit = {
val zone = target.Zone val zone = target.Zone
val attribution = zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match { val attribution = zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
case Some(player) => player.GUID case Some(player) => player.GUID
case _ => PlanetSideGUID(0) case _ => PlanetSideGUID(0)
} }
target.Destroyed = true target.Destroyed = true
Deployables.AnnounceDestroyDeployable(target, Some(if(target.Jammed) 0 seconds else 500 milliseconds)) Deployables.AnnounceDestroyDeployable(target, Some(if (target.Jammed) 0 seconds else 500 milliseconds))
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)) zone.AvatarEvents ! AvatarServiceMessage(
if(target.Health == 0) { zone.Id,
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID)) AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
)
if (target.Health == 0) {
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID)
)
} }
} }
} }

View file

@ -242,7 +242,9 @@ object GlobalDefinitions {
val lasher_projectile_ap = ProjectileDefinition(Projectiles.lasher_projectile_ap) val lasher_projectile_ap = ProjectileDefinition(Projectiles.lasher_projectile_ap)
val liberator_bomb_cluster_bomblet_projectile = ProjectileDefinition(Projectiles.liberator_bomb_cluster_bomblet_projectile) val liberator_bomb_cluster_bomblet_projectile = ProjectileDefinition(
Projectiles.liberator_bomb_cluster_bomblet_projectile
)
val liberator_bomb_cluster_projectile = ProjectileDefinition(Projectiles.liberator_bomb_cluster_projectile) val liberator_bomb_cluster_projectile = ProjectileDefinition(Projectiles.liberator_bomb_cluster_projectile)
@ -644,36 +646,32 @@ object GlobalDefinitions {
val dynomite = ToolDefinition(ObjectClass.dynomite) val dynomite = ToolDefinition(ObjectClass.dynomite)
val trhev_dualcycler = new ToolDefinition(ObjectClass.trhev_dualcycler) { val trhev_dualcycler = new ToolDefinition(ObjectClass.trhev_dualcycler) {
override def NextFireModeIndex(index : Int) : Int = index override def NextFireModeIndex(index: Int): Int = index
} }
val trhev_pounder = new ToolDefinition(ObjectClass.trhev_pounder) { val trhev_pounder = new ToolDefinition(ObjectClass.trhev_pounder) {
override def NextFireModeIndex(index : Int) : Int = { override def NextFireModeIndex(index: Int): Int = {
//TODO other modes //TODO other modes
if(index == 0 || index == 3) { if (index == 0 || index == 3) {
if(index == 0) { if (index == 0) {
3 //3-second fuse 3 //3-second fuse
} } else {
else {
0 //explode on contact 0 //explode on contact
} }
} } else if (index == 1 || index == 4) {
else if(index == 1 || index == 4) { if (index == 1) {
if(index == 1) {
4 //3-second fuse, anchored 4 //3-second fuse, anchored
} } else {
else {
1 //explode on contact, anchored 1 //explode on contact, anchored
} }
} } else {
else {
index index
} }
} }
} }
val trhev_burster = new ToolDefinition(ObjectClass.trhev_burster) { val trhev_burster = new ToolDefinition(ObjectClass.trhev_burster) {
override def NextFireModeIndex(index : Int) : Int = index override def NextFireModeIndex(index: Int): Int = index
} }
val nchev_scattercannon = ToolDefinition(ObjectClass.nchev_scattercannon) val nchev_scattercannon = ToolDefinition(ObjectClass.nchev_scattercannon)
@ -1157,13 +1155,12 @@ object GlobalDefinitions {
val vt_spawn = new BuildingDefinition(984) { Name = "vt_spawn" } val vt_spawn = new BuildingDefinition(984) { Name = "vt_spawn" }
val vt_vehicle = new BuildingDefinition(985) { Name = "vt_vehicle" } val vt_vehicle = new BuildingDefinition(985) { Name = "vt_vehicle" }
/** /**
* Given a faction, provide the standard assault melee weapon. * Given a faction, provide the standard assault melee weapon.
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the melee weapon * @return the `ToolDefinition` for the melee weapon
*/ */
def StandardMelee(faction : PlanetSideEmpire.Value) : ToolDefinition = { def StandardMelee(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => chainblade case PlanetSideEmpire.TR => chainblade
case PlanetSideEmpire.NC => magcutter case PlanetSideEmpire.NC => magcutter
@ -1177,7 +1174,7 @@ object GlobalDefinitions {
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the pistol * @return the `ToolDefinition` for the pistol
*/ */
def StandardPistol(faction : PlanetSideEmpire.Value) : ToolDefinition = { def StandardPistol(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => repeater case PlanetSideEmpire.TR => repeater
case PlanetSideEmpire.NC => isp case PlanetSideEmpire.NC => isp
@ -1193,7 +1190,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the pistol's ammo * @return thr `AmmoBoxDefinition` for the pistol's ammo
* @see `GlobalDefinitions.StandardPistol` * @see `GlobalDefinitions.StandardPistol`
*/ */
def StandardPistolAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def StandardPistolAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => bullet_9mm case PlanetSideEmpire.TR => bullet_9mm
case PlanetSideEmpire.NC => shotgun_shell case PlanetSideEmpire.NC => shotgun_shell
@ -1208,7 +1205,7 @@ object GlobalDefinitions {
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the pistol * @return the `ToolDefinition` for the pistol
*/ */
def MediumPistol(faction : PlanetSideEmpire.Value) : ToolDefinition = { def MediumPistol(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => anniversary_guna case PlanetSideEmpire.TR => anniversary_guna
case PlanetSideEmpire.NC => anniversary_gun case PlanetSideEmpire.NC => anniversary_gun
@ -1223,7 +1220,7 @@ object GlobalDefinitions {
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the rifle * @return the `ToolDefinition` for the rifle
*/ */
def MediumRifle(faction : PlanetSideEmpire.Value) : ToolDefinition = { def MediumRifle(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => cycler case PlanetSideEmpire.TR => cycler
case PlanetSideEmpire.NC => gauss case PlanetSideEmpire.NC => gauss
@ -1239,7 +1236,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the rifle's ammo * @return thr `AmmoBoxDefinition` for the rifle's ammo
* @see `GlobalDefinitions.MediumRifle` * @see `GlobalDefinitions.MediumRifle`
*/ */
def MediumRifleAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def MediumRifleAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => bullet_9mm case PlanetSideEmpire.TR => bullet_9mm
case PlanetSideEmpire.NC => bullet_9mm case PlanetSideEmpire.NC => bullet_9mm
@ -1247,6 +1244,7 @@ object GlobalDefinitions {
case PlanetSideEmpire.NEUTRAL => bullet_9mm case PlanetSideEmpire.NEUTRAL => bullet_9mm
} }
} }
/** /**
* For a given faction, provide the AP ammunition for the medium assault rifle. * For a given faction, provide the AP ammunition for the medium assault rifle.
* The ammunition value here must work with the result of obtaining the rifle using the faction. * The ammunition value here must work with the result of obtaining the rifle using the faction.
@ -1254,7 +1252,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the rifle's ammo * @return thr `AmmoBoxDefinition` for the rifle's ammo
* @see `GlobalDefinitions.MediumRifle` * @see `GlobalDefinitions.MediumRifle`
*/ */
def MediumRifleAPAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def MediumRifleAPAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => bullet_9mm_AP case PlanetSideEmpire.TR => bullet_9mm_AP
case PlanetSideEmpire.NC => bullet_9mm_AP case PlanetSideEmpire.NC => bullet_9mm_AP
@ -1269,7 +1267,7 @@ object GlobalDefinitions {
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the rifle * @return the `ToolDefinition` for the rifle
*/ */
def HeavyRifle(faction : PlanetSideEmpire.Value) : ToolDefinition = { def HeavyRifle(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => mini_chaingun case PlanetSideEmpire.TR => mini_chaingun
case PlanetSideEmpire.NC => r_shotgun case PlanetSideEmpire.NC => r_shotgun
@ -1285,7 +1283,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the rifle's ammo * @return thr `AmmoBoxDefinition` for the rifle's ammo
* @see `GlobalDefinitions.HeavyRifle` * @see `GlobalDefinitions.HeavyRifle`
*/ */
def HeavyRifleAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def HeavyRifleAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => bullet_9mm case PlanetSideEmpire.TR => bullet_9mm
case PlanetSideEmpire.NC => shotgun_shell case PlanetSideEmpire.NC => shotgun_shell
@ -1301,7 +1299,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the rifle's ammo * @return thr `AmmoBoxDefinition` for the rifle's ammo
* @see `GlobalDefinitions.HeavyRifle` * @see `GlobalDefinitions.HeavyRifle`
*/ */
def HeavyRifleAPAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def HeavyRifleAPAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => bullet_9mm_AP case PlanetSideEmpire.TR => bullet_9mm_AP
case PlanetSideEmpire.NC => shotgun_shell_AP case PlanetSideEmpire.NC => shotgun_shell_AP
@ -1315,7 +1313,7 @@ object GlobalDefinitions {
* @param faction the faction * @param faction the faction
* @return the `ToolDefinition` for the launcher * @return the `ToolDefinition` for the launcher
*/ */
def AntiVehicularLauncher(faction : PlanetSideEmpire.Value) : ToolDefinition = { def AntiVehicularLauncher(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => striker case PlanetSideEmpire.TR => striker
case PlanetSideEmpire.NC => hunterseeker case PlanetSideEmpire.NC => hunterseeker
@ -1331,7 +1329,7 @@ object GlobalDefinitions {
* @return thr `AmmoBoxDefinition` for the launcher's ammo * @return thr `AmmoBoxDefinition` for the launcher's ammo
* @see `GlobalDefinitions.AntiVehicular` * @see `GlobalDefinitions.AntiVehicular`
*/ */
def AntiVehicularAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def AntiVehicularAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => striker_missile_ammo case PlanetSideEmpire.TR => striker_missile_ammo
case PlanetSideEmpire.NC => hunter_seeker_missile case PlanetSideEmpire.NC => hunter_seeker_missile
@ -1340,33 +1338,29 @@ object GlobalDefinitions {
} }
} }
def MAXArms(subtype : Int, faction : PlanetSideEmpire.Value) : ToolDefinition = { def MAXArms(subtype: Int, faction: PlanetSideEmpire.Value): ToolDefinition = {
if(subtype == 1) { if (subtype == 1) {
AI_MAX(faction) AI_MAX(faction)
} } else if (subtype == 2) {
else if(subtype == 2) {
AV_MAX(faction) AV_MAX(faction)
} } else if (subtype == 3) {
else if(subtype == 3) {
AA_MAX(faction) AA_MAX(faction)
} } else {
else {
suppressor //there are no common pool MAX arms suppressor //there are no common pool MAX arms
} }
} }
def isMaxArms(tdef : ToolDefinition) : Boolean = { def isMaxArms(tdef: ToolDefinition): Boolean = {
tdef match { tdef match {
case `trhev_dualcycler` | `nchev_scattercannon` | `vshev_quasar` case `trhev_dualcycler` | `nchev_scattercannon` | `vshev_quasar` | `trhev_pounder` | `nchev_falcon` |
| `trhev_pounder` | `nchev_falcon` | `vshev_comet` `vshev_comet` | `trhev_burster` | `nchev_sparrow` | `vshev_starfire` =>
| `trhev_burster` | `nchev_sparrow` | `vshev_starfire` =>
true true
case _ => case _ =>
false false
} }
} }
def AI_MAX(faction : PlanetSideEmpire.Value) : ToolDefinition = { def AI_MAX(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => trhev_dualcycler case PlanetSideEmpire.TR => trhev_dualcycler
case PlanetSideEmpire.NC => nchev_scattercannon case PlanetSideEmpire.NC => nchev_scattercannon
@ -1375,7 +1369,7 @@ object GlobalDefinitions {
} }
} }
def AI_MAXAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def AI_MAXAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => dualcycler_ammo case PlanetSideEmpire.TR => dualcycler_ammo
case PlanetSideEmpire.NC => scattercannon_ammo case PlanetSideEmpire.NC => scattercannon_ammo
@ -1384,7 +1378,7 @@ object GlobalDefinitions {
} }
} }
def AV_MAX(faction : PlanetSideEmpire.Value) : ToolDefinition = { def AV_MAX(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => trhev_pounder case PlanetSideEmpire.TR => trhev_pounder
case PlanetSideEmpire.NC => nchev_falcon case PlanetSideEmpire.NC => nchev_falcon
@ -1393,7 +1387,7 @@ object GlobalDefinitions {
} }
} }
def AV_MAXAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def AV_MAXAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => pounder_ammo case PlanetSideEmpire.TR => pounder_ammo
case PlanetSideEmpire.NC => falcon_ammo case PlanetSideEmpire.NC => falcon_ammo
@ -1402,7 +1396,7 @@ object GlobalDefinitions {
} }
} }
def AA_MAX(faction : PlanetSideEmpire.Value) : ToolDefinition = { def AA_MAX(faction: PlanetSideEmpire.Value): ToolDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => trhev_burster case PlanetSideEmpire.TR => trhev_burster
case PlanetSideEmpire.NC => nchev_sparrow case PlanetSideEmpire.NC => nchev_sparrow
@ -1411,7 +1405,7 @@ object GlobalDefinitions {
} }
} }
def AA_MAXAmmo(faction : PlanetSideEmpire.Value) : AmmoBoxDefinition = { def AA_MAXAmmo(faction: PlanetSideEmpire.Value): AmmoBoxDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => burster_ammo case PlanetSideEmpire.TR => burster_ammo
case PlanetSideEmpire.NC => sparrow_ammo case PlanetSideEmpire.NC => sparrow_ammo
@ -1420,7 +1414,7 @@ object GlobalDefinitions {
} }
} }
def PortableMannedTurret(faction :PlanetSideEmpire.Value) : TurretDeployableDefinition = { def PortableMannedTurret(faction: PlanetSideEmpire.Value): TurretDeployableDefinition = {
faction match { faction match {
case PlanetSideEmpire.TR => portable_manned_turret_tr case PlanetSideEmpire.TR => portable_manned_turret_tr
case PlanetSideEmpire.NC => portable_manned_turret_nc case PlanetSideEmpire.NC => portable_manned_turret_nc
@ -1435,7 +1429,7 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is a grenade-type weapon; `false`, otherwise * @return `true`, if it is a grenade-type weapon; `false`, otherwise
*/ */
def isGrenade(edef : EquipmentDefinition) : Boolean = { def isGrenade(edef: EquipmentDefinition): Boolean = {
edef match { edef match {
case `frag_grenade` | `jammer_grenade` | `plasma_grenade` | `dynomite` => case `frag_grenade` | `jammer_grenade` | `plasma_grenade` | `dynomite` =>
true true
@ -1450,7 +1444,7 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is a grenade-type weapon; `false`, otherwise * @return `true`, if it is a grenade-type weapon; `false`, otherwise
*/ */
def isGrenadePack(edef : EquipmentDefinition) : Boolean = { def isGrenadePack(edef: EquipmentDefinition): Boolean = {
edef match { edef match {
case `frag_cartridge` | `jammer_cartridge` | `plasma_cartridge` => case `frag_cartridge` | `jammer_cartridge` | `plasma_cartridge` =>
true true
@ -1466,13 +1460,16 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return the faction alignment, or `Neutral` * @return the faction alignment, or `Neutral`
*/ */
def isFactionWeapon(edef : EquipmentDefinition) : PlanetSideEmpire.Value = { def isFactionWeapon(edef: EquipmentDefinition): PlanetSideEmpire.Value = {
edef match { edef match {
case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` => case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` |
`trhev_dualcycler` | `trhev_pounder` | `trhev_burster` =>
PlanetSideEmpire.TR PlanetSideEmpire.TR
case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` => case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `nchev_scattercannon` |
`nchev_falcon` | `nchev_sparrow` =>
PlanetSideEmpire.NC PlanetSideEmpire.NC
case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` => case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `vshev_quasar` |
`vshev_comet` | `vshev_starfire` =>
PlanetSideEmpire.VS PlanetSideEmpire.VS
case _ => case _ =>
PlanetSideEmpire.NEUTRAL PlanetSideEmpire.NEUTRAL
@ -1485,13 +1482,19 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return the faction alignment, or `Neutral` * @return the faction alignment, or `Neutral`
*/ */
def isFactionEquipment(edef : EquipmentDefinition) : PlanetSideEmpire.Value = { def isFactionEquipment(edef: EquipmentDefinition): PlanetSideEmpire.Value = {
edef match { edef match {
case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` | `striker_missile_ammo` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` | `dualcycler_ammo` | `pounder_ammo` | `burster_ammo` => case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` |
`striker_missile_ammo` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` | `dualcycler_ammo` |
`pounder_ammo` | `burster_ammo` =>
PlanetSideEmpire.TR PlanetSideEmpire.TR
case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `hunter_seeker_missile` | `nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` | `scattercannon_ammo` | `falcon_ammo` | `sparrow_ammo` => case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `hunter_seeker_missile` |
`nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` | `scattercannon_ammo` | `falcon_ammo` |
`sparrow_ammo` =>
PlanetSideEmpire.NC PlanetSideEmpire.NC
case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `energy_cell` | `lancer_cartridge` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` | `quasar_ammo` | `comet_ammo` | `starfire_ammo` => case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `energy_cell` |
`lancer_cartridge` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` | `quasar_ammo` | `comet_ammo` |
`starfire_ammo` =>
PlanetSideEmpire.VS PlanetSideEmpire.VS
case _ => case _ =>
PlanetSideEmpire.NEUTRAL PlanetSideEmpire.NEUTRAL
@ -1504,7 +1507,7 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is; otherwise, `false` * @return `true`, if it is; otherwise, `false`
*/ */
def isCavernWeapon(edef : EquipmentDefinition) : Boolean = { def isCavernWeapon(edef: EquipmentDefinition): Boolean = {
edef match { edef match {
case `spiker` | `maelstrom` | `radiator` => true case `spiker` | `maelstrom` | `radiator` => true
case _ => false case _ => false
@ -1516,7 +1519,7 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is; otherwise, `false` * @return `true`, if it is; otherwise, `false`
*/ */
def isCavernEquipment(edef : EquipmentDefinition) : Boolean = { def isCavernEquipment(edef: EquipmentDefinition): Boolean = {
edef match { edef match {
case `spiker` | `maelstrom` | `radiator` | `ancient_ammo_combo` | `maelstrom_ammo` => true case `spiker` | `maelstrom` | `radiator` | `ancient_ammo_combo` | `maelstrom_ammo` => true
case _ => false case _ => false
@ -1530,7 +1533,7 @@ object GlobalDefinitions {
* @param edef the `EquipmentDefinition` of the item * @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is; otherwise, `false` * @return `true`, if it is; otherwise, `false`
*/ */
def isSpecialEquipment(edef : EquipmentDefinition) : Boolean = { def isSpecialEquipment(edef: EquipmentDefinition): Boolean = {
edef match { edef match {
case `super_medkit` | `super_armorkit` | `super_staminakit` | `katana` => case `super_medkit` | `super_armorkit` | `super_staminakit` | `katana` =>
true true
@ -1544,9 +1547,10 @@ object GlobalDefinitions {
* @param vdef the `VehicleDefinition` of the vehicle * @param vdef the `VehicleDefinition` of the vehicle
* @return `true`, if it is; `false`, otherwise * @return `true`, if it is; `false`, otherwise
*/ */
def isFlightVehicle(vdef : VehicleDefinition) : Boolean = { def isFlightVehicle(vdef: VehicleDefinition): Boolean = {
vdef match { vdef match {
case `mosquito` | `lightgunship` | `wasp` | `liberator` | `vulture` | `phantasm` | `lodestar` | `dropship` | `galaxy_gunship` => case `mosquito` | `lightgunship` | `wasp` | `liberator` | `vulture` | `phantasm` | `lodestar` | `dropship` |
`galaxy_gunship` =>
true true
case _ => case _ =>
false false
@ -1558,7 +1562,7 @@ object GlobalDefinitions {
* @param vdef the `VehicleDefinition` of the vehicle * @param vdef the `VehicleDefinition` of the vehicle
* @return `true`, if it can; `false`, otherwise * @return `true`, if it can; `false`, otherwise
*/ */
def isHoverVehicle(vdef : VehicleDefinition) : Boolean = { def isHoverVehicle(vdef: VehicleDefinition): Boolean = {
vdef match { vdef match {
case `twomanhoverbuggy` | `magrider` | `router` | `flail` => case `twomanhoverbuggy` | `magrider` | `router` | `flail` =>
true true
@ -1572,11 +1576,10 @@ object GlobalDefinitions {
* @param vdef the `VehicleDefinition` of the vehicle * @param vdef the `VehicleDefinition` of the vehicle
* @return `true`, if it is; `false`, otherwise * @return `true`, if it is; `false`, otherwise
*/ */
def canStationaryRotate(vdef : VehicleDefinition) : Boolean = { def canStationaryRotate(vdef: VehicleDefinition): Boolean = {
if(isFlightVehicle(vdef) || isHoverVehicle(vdef)) { if (isFlightVehicle(vdef) || isHoverVehicle(vdef)) {
true true
} } else {
else {
vdef match { vdef match {
case `lightning` | `prowler` | `vanguard` => case `lightning` | `prowler` | `vanguard` =>
true true
@ -1589,7 +1592,7 @@ object GlobalDefinitions {
/** /**
* Initialize `KitDefinition` globals. * Initialize `KitDefinition` globals.
*/ */
private def init_kit() : Unit = { private def init_kit(): Unit = {
medkit.Name = "medkit" medkit.Name = "medkit"
super_medkit.Name = "super_medkit" super_medkit.Name = "super_medkit"
@ -1602,7 +1605,7 @@ object GlobalDefinitions {
/** /**
* Initialize `ExoSuitType` globals. * Initialize `ExoSuitType` globals.
*/ */
private def init_exosuit() : Unit = { private def init_exosuit(): Unit = {
Standard.Name = "standard" Standard.Name = "standard"
Standard.MaxArmor = 50 Standard.MaxArmor = 50
Standard.InventoryScale = InventoryTile.Tile96 Standard.InventoryScale = InventoryTile.Tile96
@ -1650,8 +1653,9 @@ object GlobalDefinitions {
Infiltration.Holster(0, EquipmentSize.Pistol) Infiltration.Holster(0, EquipmentSize.Pistol)
Infiltration.Holster(4, EquipmentSize.Melee) Infiltration.Holster(4, EquipmentSize.Melee)
def CommonMaxConfig(max : SpecialExoSuitDefinition): Unit = { def CommonMaxConfig(max: SpecialExoSuitDefinition): Unit = {
max.Permissions = List(CertificationType.AIMAX,CertificationType.AVMAX, CertificationType.AAMAX, CertificationType.UniMAX) max.Permissions =
List(CertificationType.AIMAX, CertificationType.AVMAX, CertificationType.AAMAX, CertificationType.UniMAX)
max.MaxArmor = 650 max.MaxArmor = 650
max.InventoryScale = InventoryTile.Tile1612 max.InventoryScale = InventoryTile.Tile1612
max.InventoryOffset = 6 max.InventoryOffset = 6
@ -1687,10 +1691,11 @@ object GlobalDefinitions {
NCMAX.CapacitorDrainPerSecond = 4 NCMAX.CapacitorDrainPerSecond = 4
} }
/** /**
* Initialize `AmmoBoxDefinition` globals. * Initialize `AmmoBoxDefinition` globals.
*/ */
private def init_ammo() : Unit = { private def init_ammo(): Unit = {
melee_ammo.Name = "melee_ammo" melee_ammo.Name = "melee_ammo"
melee_ammo.Size = EquipmentSize.Blocked melee_ammo.Size = EquipmentSize.Blocked
@ -1707,11 +1712,11 @@ object GlobalDefinitions {
bullet_9mm.Capacity = 50 bullet_9mm.Capacity = 50
bullet_9mm.Tile = InventoryTile.Tile33 bullet_9mm.Tile = InventoryTile.Tile33
bullet_9mm_AP.Name="9mmbullet_AP" bullet_9mm_AP.Name = "9mmbullet_AP"
bullet_9mm_AP.Capacity = 50 bullet_9mm_AP.Capacity = 50
bullet_9mm_AP.Tile = InventoryTile.Tile33 bullet_9mm_AP.Tile = InventoryTile.Tile33
shotgun_shell.Name ="shotgun_shell" shotgun_shell.Name = "shotgun_shell"
shotgun_shell.Capacity = 16 shotgun_shell.Capacity = 16
shotgun_shell.Tile = InventoryTile.Tile33 shotgun_shell.Tile = InventoryTile.Tile33
@ -2001,8 +2006,8 @@ object GlobalDefinitions {
/** /**
* Initialize `ProjectileDefinition` globals. * Initialize `ProjectileDefinition` globals.
*/ */
private def init_projectile() : Unit = { private def init_projectile(): Unit = {
val projectileConverter : ProjectileConverter = new ProjectileConverter val projectileConverter: ProjectileConverter = new ProjectileConverter
no_projectile.Name = "none" no_projectile.Name = "none"
ProjectileDefinition.CalculateDerivedFields(no_projectile) ProjectileDefinition.CalculateDerivedFields(no_projectile)
@ -2020,7 +2025,7 @@ object GlobalDefinitions {
bullet_105mm_projectile.Lifespan = 4f bullet_105mm_projectile.Lifespan = 4f
ProjectileDefinition.CalculateDerivedFields(bullet_105mm_projectile) ProjectileDefinition.CalculateDerivedFields(bullet_105mm_projectile)
bullet_12mm_projectile.Name= "12mmbullet_projectile" bullet_12mm_projectile.Name = "12mmbullet_projectile"
bullet_12mm_projectile.Damage0 = 25 bullet_12mm_projectile.Damage0 = 25
bullet_12mm_projectile.Damage1 = 10 bullet_12mm_projectile.Damage1 = 10
bullet_12mm_projectile.Damage2 = 25 bullet_12mm_projectile.Damage2 = 25
@ -2772,12 +2777,30 @@ object GlobalDefinitions {
jammer_cartridge_projectile.Lifespan = 15f jammer_cartridge_projectile.Lifespan = 15f
jammer_cartridge_projectile.AdditionalEffect = true jammer_cartridge_projectile.AdditionalEffect = true
jammer_cartridge_projectile.JammerProjectile = true jammer_cartridge_projectile.JammerProjectile = true
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 EffectTarget.Category.Player,
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 EffectTarget.Validation.Player
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 ) -> 1000
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 EffectTarget.Category.Vehicle,
EffectTarget.Validation.AMS
) -> 5000
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.MotionSensor
) -> 30000
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.Spitfire
) -> 30000
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Turret,
EffectTarget.Validation.Turret
) -> 30000
jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Vehicle,
EffectTarget.Validation.VehicleNotAMS
) -> 10000
ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile) ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile)
jammer_cartridge_projectile_b.Name = "jammer_cartridge_projectile_b" jammer_cartridge_projectile_b.Name = "jammer_cartridge_projectile_b"
@ -2791,12 +2814,30 @@ object GlobalDefinitions {
jammer_cartridge_projectile_b.Lifespan = 2f jammer_cartridge_projectile_b.Lifespan = 2f
jammer_cartridge_projectile_b.AdditionalEffect = true jammer_cartridge_projectile_b.AdditionalEffect = true
jammer_cartridge_projectile_b.JammerProjectile = true jammer_cartridge_projectile_b.JammerProjectile = true
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 EffectTarget.Category.Player,
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 EffectTarget.Validation.Player
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 ) -> 1000
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 EffectTarget.Category.Vehicle,
EffectTarget.Validation.AMS
) -> 5000
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.MotionSensor
) -> 30000
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.Spitfire
) -> 30000
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Turret,
EffectTarget.Validation.Turret
) -> 30000
jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Vehicle,
EffectTarget.Validation.VehicleNotAMS
) -> 10000
ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile_b) ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile_b)
jammer_grenade_projectile.Name = "jammer_grenade_projectile" jammer_grenade_projectile.Name = "jammer_grenade_projectile"
@ -2809,12 +2850,30 @@ object GlobalDefinitions {
jammer_grenade_projectile.Lifespan = 15f jammer_grenade_projectile.Lifespan = 15f
jammer_grenade_projectile.AdditionalEffect = true jammer_grenade_projectile.AdditionalEffect = true
jammer_grenade_projectile.JammerProjectile = true jammer_grenade_projectile.JammerProjectile = true
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 EffectTarget.Category.Player,
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 EffectTarget.Validation.Player
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 ) -> 1000
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 EffectTarget.Category.Vehicle,
EffectTarget.Validation.AMS
) -> 5000
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.MotionSensor
) -> 30000
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.Spitfire
) -> 30000
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Turret,
EffectTarget.Validation.Turret
) -> 30000
jammer_grenade_projectile.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Vehicle,
EffectTarget.Validation.VehicleNotAMS
) -> 10000
ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile) ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile)
jammer_grenade_projectile_enh.Name = "jammer_grenade_projectile_enh" jammer_grenade_projectile_enh.Name = "jammer_grenade_projectile_enh"
@ -2828,12 +2887,30 @@ object GlobalDefinitions {
jammer_grenade_projectile_enh.Lifespan = 3f jammer_grenade_projectile_enh.Lifespan = 3f
jammer_grenade_projectile_enh.AdditionalEffect = true jammer_grenade_projectile_enh.AdditionalEffect = true
jammer_grenade_projectile_enh.JammerProjectile = true jammer_grenade_projectile_enh.JammerProjectile = true
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 EffectTarget.Category.Player,
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 EffectTarget.Validation.Player
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 ) -> 1000
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 EffectTarget.Category.Vehicle,
EffectTarget.Validation.AMS
) -> 5000
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.MotionSensor
) -> 30000
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Deployable,
EffectTarget.Validation.Spitfire
) -> 30000
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Turret,
EffectTarget.Validation.Turret
) -> 30000
jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(
EffectTarget.Category.Vehicle,
EffectTarget.Validation.VehicleNotAMS
) -> 10000
ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile_enh) ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile_enh)
katana_projectile.Name = "katana_projectile" katana_projectile.Name = "katana_projectile"
@ -3228,7 +3305,7 @@ object GlobalDefinitions {
phoenix_missile_guided_projectile.Lifespan = 3f phoenix_missile_guided_projectile.Lifespan = 3f
//not naturally a remote projectile, but being governed as one for convenience //not naturally a remote projectile, but being governed as one for convenience
phoenix_missile_guided_projectile.ExistsOnRemoteClients = true phoenix_missile_guided_projectile.ExistsOnRemoteClients = true
phoenix_missile_guided_projectile.RemoteClientData = (0,63) phoenix_missile_guided_projectile.RemoteClientData = (0, 63)
phoenix_missile_guided_projectile.Packet = projectileConverter phoenix_missile_guided_projectile.Packet = projectileConverter
// //
ProjectileDefinition.CalculateDerivedFields(phoenix_missile_guided_projectile) ProjectileDefinition.CalculateDerivedFields(phoenix_missile_guided_projectile)
@ -3727,7 +3804,7 @@ object GlobalDefinitions {
/** /**
* Initialize `ToolDefinition` globals. * Initialize `ToolDefinition` globals.
*/ */
private def init_tools() : Unit = { private def init_tools(): Unit = {
chainblade.Name = "chainblade" chainblade.Name = "chainblade"
chainblade.Size = EquipmentSize.Melee chainblade.Size = EquipmentSize.Melee
chainblade.AmmoTypes += melee_ammo chainblade.AmmoTypes += melee_ammo
@ -4569,7 +4646,9 @@ object GlobalDefinitions {
ace.Modes(2).Item(DeployedItem.spitfire_aa -> Set(CertificationType.FortificationEngineering)) ace.Modes(2).Item(DeployedItem.spitfire_aa -> Set(CertificationType.FortificationEngineering))
ace.Modes += new ConstructionFireMode ace.Modes += new ConstructionFireMode
ace.Modes(3).Item(DeployedItem.motionalarmsensor -> Set(CertificationType.CombatEngineering)) ace.Modes(3).Item(DeployedItem.motionalarmsensor -> Set(CertificationType.CombatEngineering))
ace.Modes(3).Item(DeployedItem.sensor_shield -> Set(CertificationType.AdvancedHacking, CertificationType.CombatEngineering)) ace
.Modes(3)
.Item(DeployedItem.sensor_shield -> Set(CertificationType.AdvancedHacking, CertificationType.CombatEngineering))
ace.Tile = InventoryTile.Tile33 ace.Tile = InventoryTile.Tile33
advanced_ace.Name = "advanced_ace" advanced_ace.Name = "advanced_ace"
@ -4619,7 +4698,8 @@ object GlobalDefinitions {
scythe.FireModes += new FireModeDefinition scythe.FireModes += new FireModeDefinition
scythe.FireModes(1).AmmoTypeIndices += 0 scythe.FireModes(1).AmmoTypeIndices += 0
scythe.FireModes(1).ProjectileTypeIndices += 0 scythe.FireModes(1).ProjectileTypeIndices += 0
scythe.FireModes(1).AmmoSlotIndex = 1 //note: the scythe has two magazines using a single pool; however, it can not ammo-switch or mode-switch scythe.FireModes(1).AmmoSlotIndex =
1 //note: the scythe has two magazines using a single pool; however, it can not ammo-switch or mode-switch
scythe.FireModes(1).Magazine = 250 scythe.FireModes(1).Magazine = 250
chaingun_p.Name = "chaingun_p" chaingun_p.Name = "chaingun_p"
@ -5191,7 +5271,7 @@ object GlobalDefinitions {
/** /**
* Initialize `VehicleDefinition` globals. * Initialize `VehicleDefinition` globals.
*/ */
private def init_vehicles() : Unit = { private def init_vehicles(): Unit = {
fury.Name = "fury" fury.Name = "fury"
fury.MaxHealth = 650 fury.MaxHealth = 650
fury.Damageable = true fury.Damageable = true
@ -5480,7 +5560,7 @@ object GlobalDefinitions {
aurora.AutoPilotSpeeds = (18, 6) aurora.AutoPilotSpeeds = (18, 6)
aurora.DestroyedModel = Some(DestroyedVehicle.MediumTransport) aurora.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
aurora.Subtract.Damage1 = 7 aurora.Subtract.Damage1 = 7
aurora.JackingDuration = Array(0, 25, 8 ,5) aurora.JackingDuration = Array(0, 25, 8, 5)
apc_tr.Name = "apc_tr" // Juggernaut apc_tr.Name = "apc_tr" // Juggernaut
apc_tr.MaxHealth = 6000 apc_tr.MaxHealth = 6000
@ -5653,7 +5733,7 @@ object GlobalDefinitions {
lightning.AutoPilotSpeeds = (20, 8) lightning.AutoPilotSpeeds = (20, 8)
lightning.DestroyedModel = Some(DestroyedVehicle.Lightning) lightning.DestroyedModel = Some(DestroyedVehicle.Lightning)
lightning.Subtract.Damage1 = 7 lightning.Subtract.Damage1 = 7
lightning.JackingDuration = Array(0, 20, 7 ,5) lightning.JackingDuration = Array(0, 20, 7, 5)
prowler.Name = "prowler" prowler.Name = "prowler"
prowler.MaxHealth = 4800 prowler.MaxHealth = 4800
@ -5743,7 +5823,7 @@ object GlobalDefinitions {
ant.Packet = utilityConverter ant.Packet = utilityConverter
ant.DestroyedModel = Some(DestroyedVehicle.Ant) ant.DestroyedModel = Some(DestroyedVehicle.Ant)
ant.Subtract.Damage1 = 5 ant.Subtract.Damage1 = 5
ant.JackingDuration = Array (0, 60, 20, 15) ant.JackingDuration = Array(0, 60, 20, 15)
ams.Name = "ams" ams.Name = "ams"
ams.MaxHealth = 3000 ams.MaxHealth = 3000
@ -5957,7 +6037,8 @@ object GlobalDefinitions {
vulture.TrunkLocation = Vector3(-0.76f, -1.88f, 0f) vulture.TrunkLocation = Vector3(-0.76f, -1.88f, 0f)
vulture.AutoPilotSpeeds = (0, 4) vulture.AutoPilotSpeeds = (0, 4)
vulture.Packet = variantConverter vulture.Packet = variantConverter
vulture.DestroyedModel = Some(DestroyedVehicle.Liberator) //add_property vulture destroyedphysics liberator_destroyed vulture.DestroyedModel =
Some(DestroyedVehicle.Liberator) //add_property vulture destroyedphysics liberator_destroyed
vulture.Subtract.Damage1 = 5 vulture.Subtract.Damage1 = 5
vulture.JackingDuration = Array(0, 30, 10, 5) vulture.JackingDuration = Array(0, 30, 10, 5)
@ -6058,7 +6139,8 @@ object GlobalDefinitions {
galaxy_gunship.TrunkLocation = Vector3(-9.85f, 0f, 0f) galaxy_gunship.TrunkLocation = Vector3(-9.85f, 0f, 0f)
galaxy_gunship.AutoPilotSpeeds = (0, 4) galaxy_gunship.AutoPilotSpeeds = (0, 4)
galaxy_gunship.Packet = variantConverter galaxy_gunship.Packet = variantConverter
galaxy_gunship.DestroyedModel = Some(DestroyedVehicle.Dropship) //the adb calls out a galaxy_gunship_destroyed but no such asset exists galaxy_gunship.DestroyedModel =
Some(DestroyedVehicle.Dropship) //the adb calls out a galaxy_gunship_destroyed but no such asset exists
galaxy_gunship.Subtract.Damage1 = 7 galaxy_gunship.Subtract.Damage1 = 7
galaxy_gunship.JackingDuration = Array(0, 60, 20, 10) galaxy_gunship.JackingDuration = Array(0, 60, 20, 10)
@ -6136,7 +6218,7 @@ object GlobalDefinitions {
/** /**
* Initialize `Deployable` globals. * Initialize `Deployable` globals.
*/ */
private def init_deployables() : Unit = { private def init_deployables(): Unit = {
boomer.Name = "boomer" boomer.Name = "boomer"
boomer.Descriptor = "Boomers" boomer.Descriptor = "Boomers"
boomer.MaxHealth = 100 boomer.MaxHealth = 100
@ -6327,7 +6409,7 @@ object GlobalDefinitions {
/** /**
* Initialize `Miscellaneous` globals. * Initialize `Miscellaneous` globals.
*/ */
private def initMiscellaneous() : Unit = { private def initMiscellaneous(): Unit = {
ams_respawn_tube.Name = "ams_respawn_tube" ams_respawn_tube.Name = "ams_respawn_tube"
ams_respawn_tube.Delay = 5 ams_respawn_tube.Delay = 5
ams_respawn_tube.SpecificPointFunc = SpawnPoint.AMS ams_respawn_tube.SpecificPointFunc = SpawnPoint.AMS
@ -6351,9 +6433,16 @@ object GlobalDefinitions {
spawn_terminal.Repairable = false spawn_terminal.Repairable = false
order_terminal.Name = "order_terminal" order_terminal.Name = "order_terminal"
order_terminal.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons) order_terminal.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(
order_terminal.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(EquipmentTerminalDefinition.suits ++ EquipmentTerminalDefinition.maxSuits, EquipmentTerminalDefinition.maxAmmo) EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons
order_terminal.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons) )
order_terminal.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(
EquipmentTerminalDefinition.suits ++ EquipmentTerminalDefinition.maxSuits,
EquipmentTerminalDefinition.maxAmmo
)
order_terminal.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons
)
order_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) order_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
order_terminal.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage() order_terminal.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage()
order_terminal.SellEquipmentByDefault = true order_terminal.SellEquipmentByDefault = true
@ -6364,9 +6453,16 @@ object GlobalDefinitions {
order_terminal.Subtract.Damage1 = 8 order_terminal.Subtract.Damage1 = 8
order_terminala.Name = "order_terminala" order_terminala.Name = "order_terminala"
order_terminala.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons) order_terminala.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(
order_terminala.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(EquipmentTerminalDefinition.suits, EquipmentTerminalDefinition.maxAmmo) EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons
order_terminala.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons) )
order_terminala.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(
EquipmentTerminalDefinition.suits,
EquipmentTerminalDefinition.maxAmmo
)
order_terminala.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons
)
order_terminala.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) order_terminala.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
order_terminala.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage() order_terminala.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage()
order_terminala.Tab(4).asInstanceOf[OrderTerminalDefinition.InfantryLoadoutPage].Exclude = ExoSuitType.MAX order_terminala.Tab(4).asInstanceOf[OrderTerminalDefinition.InfantryLoadoutPage].Exclude = ExoSuitType.MAX
@ -6375,9 +6471,16 @@ object GlobalDefinitions {
order_terminala.Repairable = false order_terminala.Repairable = false
order_terminalb.Name = "order_terminalb" order_terminalb.Name = "order_terminalb"
order_terminalb.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons) order_terminalb.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(
order_terminalb.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(EquipmentTerminalDefinition.suits, EquipmentTerminalDefinition.maxAmmo) EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons
order_terminalb.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons) )
order_terminalb.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(
EquipmentTerminalDefinition.suits,
EquipmentTerminalDefinition.maxAmmo
)
order_terminalb.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons
)
order_terminalb.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) order_terminalb.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
order_terminalb.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage() order_terminalb.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage()
order_terminalb.Tab(4).asInstanceOf[OrderTerminalDefinition.InfantryLoadoutPage].Exclude = ExoSuitType.MAX order_terminalb.Tab(4).asInstanceOf[OrderTerminalDefinition.InfantryLoadoutPage].Exclude = ExoSuitType.MAX
@ -6386,9 +6489,16 @@ object GlobalDefinitions {
order_terminalb.Repairable = false order_terminalb.Repairable = false
vanu_equipment_term.Name = "vanu_equipment_term" vanu_equipment_term.Name = "vanu_equipment_term"
vanu_equipment_term.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons) vanu_equipment_term.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(
vanu_equipment_term.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(EquipmentTerminalDefinition.suits ++ EquipmentTerminalDefinition.maxSuits, EquipmentTerminalDefinition.maxAmmo) EquipmentTerminalDefinition.infantryAmmunition ++ EquipmentTerminalDefinition.infantryWeapons
vanu_equipment_term.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons) )
vanu_equipment_term.Tab += 1 -> OrderTerminalDefinition.ArmorWithAmmoPage(
EquipmentTerminalDefinition.suits ++ EquipmentTerminalDefinition.maxSuits,
EquipmentTerminalDefinition.maxAmmo
)
vanu_equipment_term.Tab += 2 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.supportAmmunition ++ EquipmentTerminalDefinition.supportWeapons
)
vanu_equipment_term.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) vanu_equipment_term.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
vanu_equipment_term.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage() vanu_equipment_term.Tab += 4 -> OrderTerminalDefinition.InfantryLoadoutPage()
vanu_equipment_term.SellEquipmentByDefault = true vanu_equipment_term.SellEquipmentByDefault = true
@ -6417,7 +6527,10 @@ object GlobalDefinitions {
implant_terminal_interface.RepairIfDestroyed = true implant_terminal_interface.RepairIfDestroyed = true
ground_vehicle_terminal.Name = "ground_vehicle_terminal" ground_vehicle_terminal.Name = "ground_vehicle_terminal"
ground_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.groundVehicles, VehicleTerminalDefinition.trunk) ground_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.groundVehicles,
VehicleTerminalDefinition.trunk
)
ground_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() ground_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
ground_vehicle_terminal.MaxHealth = 500 ground_vehicle_terminal.MaxHealth = 500
ground_vehicle_terminal.Damageable = true ground_vehicle_terminal.Damageable = true
@ -6426,7 +6539,10 @@ object GlobalDefinitions {
ground_vehicle_terminal.Subtract.Damage1 = 8 ground_vehicle_terminal.Subtract.Damage1 = 8
air_vehicle_terminal.Name = "air_vehicle_terminal" air_vehicle_terminal.Name = "air_vehicle_terminal"
air_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.flight1Vehicles, VehicleTerminalDefinition.trunk) air_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.flight1Vehicles,
VehicleTerminalDefinition.trunk
)
air_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() air_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
air_vehicle_terminal.MaxHealth = 500 air_vehicle_terminal.MaxHealth = 500
air_vehicle_terminal.Damageable = true air_vehicle_terminal.Damageable = true
@ -6435,7 +6551,10 @@ object GlobalDefinitions {
air_vehicle_terminal.Subtract.Damage1 = 8 air_vehicle_terminal.Subtract.Damage1 = 8
dropship_vehicle_terminal.Name = "dropship_vehicle_terminal" dropship_vehicle_terminal.Name = "dropship_vehicle_terminal"
dropship_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.flight1Vehicles ++ VehicleTerminalDefinition.flight2Vehicles, VehicleTerminalDefinition.trunk) dropship_vehicle_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.flight1Vehicles ++ VehicleTerminalDefinition.flight2Vehicles,
VehicleTerminalDefinition.trunk
)
dropship_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() dropship_vehicle_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
dropship_vehicle_terminal.MaxHealth = 500 dropship_vehicle_terminal.MaxHealth = 500
dropship_vehicle_terminal.Damageable = true dropship_vehicle_terminal.Damageable = true
@ -6444,7 +6563,10 @@ object GlobalDefinitions {
dropship_vehicle_terminal.Subtract.Damage1 = 8 dropship_vehicle_terminal.Subtract.Damage1 = 8
vehicle_terminal_combined.Name = "vehicle_terminal_combined" vehicle_terminal_combined.Name = "vehicle_terminal_combined"
vehicle_terminal_combined.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.flight1Vehicles ++ VehicleTerminalDefinition.groundVehicles, VehicleTerminalDefinition.trunk) vehicle_terminal_combined.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.flight1Vehicles ++ VehicleTerminalDefinition.groundVehicles,
VehicleTerminalDefinition.trunk
)
vehicle_terminal_combined.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() vehicle_terminal_combined.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
vehicle_terminal_combined.MaxHealth = 500 vehicle_terminal_combined.MaxHealth = 500
vehicle_terminal_combined.Damageable = true vehicle_terminal_combined.Damageable = true
@ -6453,7 +6575,10 @@ object GlobalDefinitions {
vehicle_terminal_combined.Subtract.Damage1 = 8 vehicle_terminal_combined.Subtract.Damage1 = 8
vanu_air_vehicle_term.Name = "vanu_air_vehicle_term" vanu_air_vehicle_term.Name = "vanu_air_vehicle_term"
vanu_air_vehicle_term.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.flight1Vehicles, VehicleTerminalDefinition.trunk) vanu_air_vehicle_term.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.flight1Vehicles,
VehicleTerminalDefinition.trunk
)
vanu_air_vehicle_term.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() vanu_air_vehicle_term.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
vanu_air_vehicle_term.MaxHealth = 500 vanu_air_vehicle_term.MaxHealth = 500
vanu_air_vehicle_term.Damageable = true vanu_air_vehicle_term.Damageable = true
@ -6462,7 +6587,10 @@ object GlobalDefinitions {
vanu_air_vehicle_term.Subtract.Damage1 = 8 vanu_air_vehicle_term.Subtract.Damage1 = 8
vanu_vehicle_term.Name = "vanu_vehicle_term" vanu_vehicle_term.Name = "vanu_vehicle_term"
vanu_vehicle_term.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.groundVehicles, VehicleTerminalDefinition.trunk) vanu_vehicle_term.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.groundVehicles,
VehicleTerminalDefinition.trunk
)
vanu_vehicle_term.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() vanu_vehicle_term.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
vanu_vehicle_term.MaxHealth = 500 vanu_vehicle_term.MaxHealth = 500
vanu_vehicle_term.Damageable = true vanu_vehicle_term.Damageable = true
@ -6471,7 +6599,10 @@ object GlobalDefinitions {
vanu_vehicle_term.Subtract.Damage1 = 8 vanu_vehicle_term.Subtract.Damage1 = 8
bfr_terminal.Name = "bfr_terminal" bfr_terminal.Name = "bfr_terminal"
bfr_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.bfrVehicles, VehicleTerminalDefinition.trunk) bfr_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(
VehicleTerminalDefinition.bfrVehicles,
VehicleTerminalDefinition.trunk
)
bfr_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() bfr_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
bfr_terminal.MaxHealth = 500 bfr_terminal.MaxHealth = 500
bfr_terminal.Damageable = true bfr_terminal.Damageable = true
@ -6632,14 +6763,18 @@ object GlobalDefinitions {
lodestar_repair_terminal.Repairable = false lodestar_repair_terminal.Repairable = false
multivehicle_rearm_terminal.Name = "multivehicle_rearm_terminal" multivehicle_rearm_terminal.Name = "multivehicle_rearm_terminal"
multivehicle_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) multivehicle_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.vehicleAmmunition
)
multivehicle_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() multivehicle_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
multivehicle_rearm_terminal.SellEquipmentByDefault = true //TODO ? multivehicle_rearm_terminal.SellEquipmentByDefault = true //TODO ?
multivehicle_rearm_terminal.Damageable = false multivehicle_rearm_terminal.Damageable = false
multivehicle_rearm_terminal.Repairable = false multivehicle_rearm_terminal.Repairable = false
bfr_rearm_terminal.Name = "bfr_rearm_terminal" bfr_rearm_terminal.Name = "bfr_rearm_terminal"
bfr_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(Map.empty[String, ()=>Equipment]) //TODO add stock to page bfr_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(
Map.empty[String, () => Equipment]
) //TODO add stock to page
bfr_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() bfr_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
bfr_rearm_terminal.SellEquipmentByDefault = true //TODO ? bfr_rearm_terminal.SellEquipmentByDefault = true //TODO ?
bfr_rearm_terminal.Damageable = false bfr_rearm_terminal.Damageable = false
@ -6653,7 +6788,9 @@ object GlobalDefinitions {
air_rearm_terminal.Repairable = false air_rearm_terminal.Repairable = false
ground_rearm_terminal.Name = "ground_rearm_terminal" ground_rearm_terminal.Name = "ground_rearm_terminal"
ground_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition) ground_rearm_terminal.Tab += 3 -> OrderTerminalDefinition.EquipmentPage(
EquipmentTerminalDefinition.vehicleAmmunition
)
ground_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage() ground_rearm_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
ground_rearm_terminal.SellEquipmentByDefault = true //TODO ? ground_rearm_terminal.SellEquipmentByDefault = true //TODO ?
ground_rearm_terminal.Damageable = false ground_rearm_terminal.Damageable = false

View file

@ -14,47 +14,54 @@ import net.psforever.types.{ExoSuitType, ImplantType}
* Being jammed de-activates the implant, put it into a state of "not being ready," and causes the initialization to repeat. * Being jammed de-activates the implant, put it into a state of "not being ready," and causes the initialization to repeat.
*/ */
class ImplantSlot { class ImplantSlot {
/** is this slot available for holding an implant */ /** is this slot available for holding an implant */
private var unlocked : Boolean = false private var unlocked: Boolean = false
/** whether this implant is ready for use */ /** whether this implant is ready for use */
private var initialized : Boolean = false private var initialized: Boolean = false
/** */
private var initializeTime : Long = 0L /**
*/
private var initializeTime: Long = 0L
/** is this implant active */ /** is this implant active */
private var active : Boolean = false private var active: Boolean = false
/** what implant is currently installed in this slot; None if there is no implant currently installed */ /** what implant is currently installed in this slot; None if there is no implant currently installed */
private var implant : Option[ImplantDefinition] = None private var implant: Option[ImplantDefinition] = None
def InitializeTime : Long = initializeTime def InitializeTime: Long = initializeTime
def InitializeTime_=(time : Long) : Long = { def InitializeTime_=(time: Long): Long = {
initializeTime = time initializeTime = time
InitializeTime InitializeTime
} }
def Unlocked : Boolean = unlocked def Unlocked: Boolean = unlocked
def Unlocked_=(lock : Boolean) : Boolean = { def Unlocked_=(lock: Boolean): Boolean = {
unlocked = lock || unlocked //do not let re-lock unlocked = lock || unlocked //do not let re-lock
Unlocked Unlocked
} }
def Initialized : Boolean = initialized def Initialized: Boolean = initialized
def Initialized_=(init : Boolean) : Boolean = { def Initialized_=(init: Boolean): Boolean = {
initialized = Installed.isDefined && init initialized = Installed.isDefined && init
Active = Active && initialized //can not be active just yet Active = Active && initialized //can not be active just yet
Initialized Initialized
} }
def Active : Boolean = active def Active: Boolean = active
def Active_=(state : Boolean) : Boolean = { def Active_=(state: Boolean): Boolean = {
active = Initialized && state active = Initialized && state
Active Active
} }
def Implant : ImplantType.Value = Installed match { def Implant: ImplantType.Value =
Installed match {
case Some(idef) => case Some(idef) =>
idef.Type idef.Type
case None => case None =>
@ -63,12 +70,12 @@ class ImplantSlot {
ImplantType.None ImplantType.None
} }
def Implant_=(anImplant : ImplantDefinition) : ImplantType.Value = { def Implant_=(anImplant: ImplantDefinition): ImplantType.Value = {
Implant_=(Some(anImplant)) Implant_=(Some(anImplant))
} }
def Implant_=(anImplant : Option[ImplantDefinition]) : ImplantType.Value = { def Implant_=(anImplant: Option[ImplantDefinition]): ImplantType.Value = {
if(Unlocked) { if (Unlocked) {
anImplant match { anImplant match {
case Some(_) => case Some(_) =>
implant = anImplant implant = anImplant
@ -81,20 +88,20 @@ class ImplantSlot {
Implant Implant
} }
def Installed : Option[ImplantDefinition] = implant def Installed: Option[ImplantDefinition] = implant
def MaxTimer : Long = Implant match { def MaxTimer: Long =
Implant match {
case ImplantType.None => case ImplantType.None =>
-1L -1L
case _ => case _ =>
Installed.get.InitializationDuration Installed.get.InitializationDuration
} }
def ActivationCharge : Int = { def ActivationCharge: Int = {
if(Active) { if (Active) {
Installed.get.ActivationStaminaCost Installed.get.ActivationStaminaCost
} } else {
else {
0 0
} }
} }
@ -104,24 +111,23 @@ class ImplantSlot {
* @param suit the exo-suit being worn * @param suit the exo-suit being worn
* @return the amount of stamina (energy) that is consumed * @return the amount of stamina (energy) that is consumed
*/ */
def Charge(suit : ExoSuitType.Value) : Int = { def Charge(suit: ExoSuitType.Value): Int = {
if(Active) { if (Active) {
val inst = Installed.get val inst = Installed.get
inst.StaminaCost inst.StaminaCost
} } else {
else {
0 0
} }
} }
def Jammed() : Unit = { def Jammed(): Unit = {
Active = false Active = false
Initialized = false Initialized = false
} }
} }
object ImplantSlot { object ImplantSlot {
def apply() : ImplantSlot = { def apply(): ImplantSlot = {
new ImplantSlot() new ImplantSlot()
} }
} }

View file

@ -8,12 +8,12 @@ import net.psforever.objects.equipment.Equipment
* A one-time-use recovery item that can be applied by the player while held within their inventory. * A one-time-use recovery item that can be applied by the player while held within their inventory.
* @param kitDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields * @param kitDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/ */
class Kit(private val kitDef : KitDefinition) extends Equipment { class Kit(private val kitDef: KitDefinition) extends Equipment {
def Definition : KitDefinition = kitDef def Definition: KitDefinition = kitDef
} }
object Kit { object Kit {
def apply(kitDef : KitDefinition) : Kit = { def apply(kitDef: KitDefinition): Kit = {
new Kit(kitDef) new Kit(kitDef)
} }
} }

View file

@ -8,14 +8,15 @@ import scala.collection.concurrent.{Map, TrieMap}
* `LivePlayerList` is a singleton and this private class lacks exposure. * `LivePlayerList` is a singleton and this private class lacks exposure.
*/ */
private class LivePlayerList { private class LivePlayerList {
/** key - the session id; value - a `Player` object */
private val sessionMap : Map[Long, Avatar] = new TrieMap[Long, Avatar]
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = { /** key - the session id; value - a `Player` object */
private val sessionMap: Map[Long, Avatar] = new TrieMap[Long, Avatar]
def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = {
sessionMap.filter(predicate).values.toList sessionMap.filter(predicate).values.toList
} }
def Add(sessionId : Long, avatar : Avatar) : Boolean = { def Add(sessionId: Long, avatar: Avatar): Boolean = {
sessionMap.values.find(char => char.equals(avatar)) match { sessionMap.values.find(char => char.equals(avatar)) match {
case None => case None =>
sessionMap.putIfAbsent(sessionId, avatar).isEmpty sessionMap.putIfAbsent(sessionId, avatar).isEmpty
@ -24,11 +25,11 @@ private class LivePlayerList {
} }
} }
def Remove(sessionId : Long) : Option[Avatar] = { def Remove(sessionId: Long): Option[Avatar] = {
sessionMap.remove(sessionId) sessionMap.remove(sessionId)
} }
def Shutdown : List[Avatar] = { def Shutdown: List[Avatar] = {
val list = sessionMap.values.toList val list = sessionMap.values.toList
sessionMap.clear sessionMap.clear
list list
@ -48,8 +49,9 @@ private class LivePlayerList {
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`LivePlayerList.Remove(session)` * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`LivePlayerList.Remove(session)`
*/ */
object LivePlayerList { object LivePlayerList {
/** As `LivePlayerList` is a singleton, an object of `LivePlayerList` is automatically instantiated. */ /** As `LivePlayerList` is a singleton, an object of `LivePlayerList` is automatically instantiated. */
private val Instance : LivePlayerList = new LivePlayerList private val Instance: LivePlayerList = new LivePlayerList
/** /**
* Given some criteria, examine the mapping of user characters and find the ones that fulfill the requirements.<br> * Given some criteria, examine the mapping of user characters and find the ones that fulfill the requirements.<br>
@ -61,7 +63,7 @@ object LivePlayerList {
* @param predicate the conditions for filtering the live `Player`s * @param predicate the conditions for filtering the live `Player`s
* @return a list of users's `Player`s that fit the criteria * @return a list of users's `Player`s that fit the criteria
*/ */
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = Instance.WorldPopulation(predicate) def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = Instance.WorldPopulation(predicate)
/** /**
* Create a mapped entry between the user's session and a user's character. * Create a mapped entry between the user's session and a user's character.
@ -70,7 +72,7 @@ object LivePlayerList {
* @param avatar the character * @param avatar the character
* @return `true`, if the session was association was made; `false`, otherwise * @return `true`, if the session was association was made; `false`, otherwise
*/ */
def Add(sessionId : Long, avatar : Avatar) : Boolean = Instance.Add(sessionId, avatar) def Add(sessionId: Long, avatar: Avatar): Boolean = Instance.Add(sessionId, avatar)
/** /**
* Remove all entries related to the given session identifier from the mappings. * Remove all entries related to the given session identifier from the mappings.
@ -78,11 +80,11 @@ object LivePlayerList {
* @param sessionId the session * @param sessionId the session
* @return any character that was afffected by the mapping removal * @return any character that was afffected by the mapping removal
*/ */
def Remove(sessionId : Long) : Option[Avatar] = Instance.Remove(sessionId) def Remove(sessionId: Long): Option[Avatar] = Instance.Remove(sessionId)
/** /**
* Hastily remove all mappings and ids. * Hastily remove all mappings and ids.
* @return an unsorted list of the characters that were still online * @return an unsorted list of the characters that were still online
*/ */
def Shutdown : List[Avatar] = Instance.Shutdown def Shutdown: List[Avatar] = Instance.Shutdown
} }

View file

@ -30,7 +30,7 @@ object LocalProjectile {
* @param context a context to allow the object to properly set up `ActorSystem` functionality * @param context a context to allow the object to properly set up `ActorSystem` functionality
* @return the `LocalProjectile` object * @return the `LocalProjectile` object
*/ */
def Constructor(id : Int, context : ActorContext) : LocalProjectile = { def Constructor(id: Int, context: ActorContext): LocalProjectile = {
new LocalProjectile() new LocalProjectile()
} }
} }

View file

@ -19,62 +19,60 @@ import services.avatar.{AvatarAction, AvatarServiceMessage}
* The `Player` class refers to it as the "fifth slot" as its permanent slot number is encoded as `0x85`. * The `Player` class refers to it as the "fifth slot" as its permanent slot number is encoded as `0x85`.
* The inventory of this object is accessed using a game world `Locker` object (`mb_locker`). * The inventory of this object is accessed using a game world `Locker` object (`mb_locker`).
*/ */
class LockerContainer extends PlanetSideServerObject class LockerContainer extends PlanetSideServerObject with Container {
with Container { private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private val inventory = GridInventory(30, 20) private val inventory = GridInventory(30, 20)
def Faction : PlanetSideEmpire.Value = faction def Faction: PlanetSideEmpire.Value = faction
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = { override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
faction = fact faction = fact
Faction Faction
} }
def Inventory : GridInventory = inventory def Inventory: GridInventory = inventory
def VisibleSlots : Set[Int] = Set.empty[Int] def VisibleSlots: Set[Int] = Set.empty[Int]
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container def Definition: EquipmentDefinition = GlobalDefinitions.locker_container
} }
object LockerContainer { object LockerContainer {
def apply() : LockerContainer = { def apply(): LockerContainer = {
new LockerContainer() new LockerContainer()
} }
} }
class LockerEquipment(locker : LockerContainer) extends Equipment class LockerEquipment(locker: LockerContainer) extends Equipment with Container {
with Container {
private val obj = locker private val obj = locker
override def GUID : PlanetSideGUID = obj.GUID override def GUID: PlanetSideGUID = obj.GUID
override def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = obj.GUID_=(guid) override def GUID_=(guid: PlanetSideGUID): PlanetSideGUID = obj.GUID_=(guid)
override def HasGUID : Boolean = obj.HasGUID override def HasGUID: Boolean = obj.HasGUID
override def Invalidate() : Unit = obj.Invalidate() override def Invalidate(): Unit = obj.Invalidate()
override def Faction : PlanetSideEmpire.Value = obj.Faction override def Faction: PlanetSideEmpire.Value = obj.Faction
def Inventory : GridInventory = obj.Inventory def Inventory: GridInventory = obj.Inventory
def VisibleSlots : Set[Int] = Set.empty[Int] def VisibleSlots: Set[Int] = Set.empty[Int]
def Definition : EquipmentDefinition = obj.Definition def Definition: EquipmentDefinition = obj.Definition
} }
class LockerContainerControl(locker : LockerContainer, toChannel : String) extends Actor class LockerContainerControl(locker: LockerContainer, toChannel: String) extends Actor with ContainableBehavior {
with ContainableBehavior {
def ContainerObject = locker def ContainerObject = locker
def receive : Receive = containerBehavior def receive: Receive =
containerBehavior
.orElse { .orElse {
case _ => ; case _ => ;
} }
def MessageDeferredCallback(msg : Any) : Unit = { def MessageDeferredCallback(msg: Any): Unit = {
msg match { msg match {
case Containable.MoveItem(_, item, _) => case Containable.MoveItem(_, item, _) =>
//momentarily put item back where it was originally //momentarily put item back where it was originally
@ -91,12 +89,12 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
} }
} }
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = { def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
val zone = locker.Zone val zone = locker.Zone
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID)) zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
} }
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = { def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
val zone = locker.Zone val zone = locker.Zone
val definition = item.Definition val definition = item.Definition
item.Faction = PlanetSideEmpire.NEUTRAL item.Faction = PlanetSideEmpire.NEUTRAL
@ -114,8 +112,14 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
) )
} }
def SwapItemCallback(item : Equipment) : Unit = { def SwapItemCallback(item: Equipment): Unit = {
val zone = locker.Zone val zone = locker.Zone
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.SendResponse(Service.defaultPlayerGUID, ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f))) zone.AvatarEvents ! AvatarServiceMessage(
toChannel,
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f)
)
)
} }
} }

View file

@ -8,7 +8,7 @@ import net.psforever.objects.equipment.{EquipmentSize, EquipmentSlot}
* Unlike conventional `EquipmentSlot` space, this size of allowable `Equipment` is fixed. * Unlike conventional `EquipmentSlot` space, this size of allowable `Equipment` is fixed.
* @param size the permanent size of the `Equipment` allowed in this slot * @param size the permanent size of the `Equipment` allowed in this slot
*/ */
class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot { class OffhandEquipmentSlot(size: EquipmentSize.Value) extends EquipmentSlot {
super.Size_=(size) super.Size_=(size)
/** /**
@ -16,10 +16,11 @@ class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot {
* @param assignSize the changed in capacity for this slot * @param assignSize the changed in capacity for this slot
* @return the capacity for this slot * @return the capacity for this slot
*/ */
override def Size_=(assignSize : EquipmentSize.Value) : EquipmentSize.Value = Size override def Size_=(assignSize: EquipmentSize.Value): EquipmentSize.Value = Size
} }
object OffhandEquipmentSlot { object OffhandEquipmentSlot {
/** /**
* An `EquipmentSlot` that can not be manipulated because its size is `Blocked` permanently. * An `EquipmentSlot` that can not be manipulated because its size is `Blocked` permanently.
*/ */

View file

@ -4,16 +4,16 @@ package net.psforever.objects
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
trait OwnableByPlayer { trait OwnableByPlayer {
private var owner : Option[PlanetSideGUID] = None private var owner: Option[PlanetSideGUID] = None
private var ownerName : Option[String] = None private var ownerName: Option[String] = None
def Owner : Option[PlanetSideGUID] = owner def Owner: Option[PlanetSideGUID] = owner
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner)) def Owner_=(owner: PlanetSideGUID): Option[PlanetSideGUID] = Owner_=(Some(owner))
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID)) def Owner_=(owner: Player): Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def Owner_=(owner: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
owner match { owner match {
case Some(_) => case Some(_) =>
this.owner = owner this.owner = owner
@ -23,13 +23,13 @@ trait OwnableByPlayer {
Owner Owner
} }
def OwnerName : Option[String] = ownerName def OwnerName: Option[String] = ownerName
def OwnerName_=(owner : String) : Option[String] = OwnerName_=(Some(owner)) def OwnerName_=(owner: String): Option[String] = OwnerName_=(Some(owner))
def OwnerName_=(owner : Player) : Option[String] = OwnerName_=(Some(owner.Name)) def OwnerName_=(owner: Player): Option[String] = OwnerName_=(Some(owner.Name))
def OwnerName_=(owner : Option[String]) : Option[String] = { def OwnerName_=(owner: Option[String]): Option[String] = {
owner match { owner match {
case Some(_) => case Some(_) =>
ownerName = owner ownerName = owner
@ -44,14 +44,14 @@ trait OwnableByPlayer {
* @param player na * @param player na
* @return na * @return na
*/ */
def AssignOwnership(player : Player) : OwnableByPlayer = AssignOwnership(Some(player)) def AssignOwnership(player: Player): OwnableByPlayer = AssignOwnership(Some(player))
/** /**
* na * na
* @param playerOpt na * @param playerOpt na
* @return na * @return na
*/ */
def AssignOwnership(playerOpt : Option[Player]) : OwnableByPlayer = { def AssignOwnership(playerOpt: Option[Player]): OwnableByPlayer = {
playerOpt match { playerOpt match {
case Some(player) => case Some(player) =>
Owner = player Owner = player

View file

@ -9,47 +9,48 @@ import net.psforever.types.Vector3
* A basic class that indicates an entity that exists somewhere in the world and has a globally unique identifier. * A basic class that indicates an entity that exists somewhere in the world and has a globally unique identifier.
*/ */
abstract class PlanetSideGameObject extends IdentifiableEntity with WorldEntity { abstract class PlanetSideGameObject extends IdentifiableEntity with WorldEntity {
private var entity : WorldEntity = new SimpleWorldEntity() private var entity: WorldEntity = new SimpleWorldEntity()
private var destroyed : Boolean = false private var destroyed: Boolean = false
def Entity : WorldEntity = entity def Entity: WorldEntity = entity
def Entity_=(newEntity : WorldEntity) : Unit = { def Entity_=(newEntity: WorldEntity): Unit = {
entity = newEntity entity = newEntity
} }
def Position : Vector3 = Entity.Position def Position: Vector3 = Entity.Position
def Position_=(vec : Vector3) : Vector3 = { def Position_=(vec: Vector3): Vector3 = {
Entity.Position = vec Entity.Position = vec
} }
def Orientation : Vector3 = Entity.Orientation def Orientation: Vector3 = Entity.Orientation
def Orientation_=(vec : Vector3) : Vector3 = { def Orientation_=(vec: Vector3): Vector3 = {
Entity.Orientation = vec Entity.Orientation = vec
} }
def Velocity : Option[Vector3] = Entity.Velocity def Velocity: Option[Vector3] = Entity.Velocity
def Velocity_=(vec : Option[Vector3]) : Option[Vector3] = { def Velocity_=(vec: Option[Vector3]): Option[Vector3] = {
Entity.Velocity = vec Entity.Velocity = vec
} }
def Destroyed : Boolean = destroyed def Destroyed: Boolean = destroyed
def Destroyed_=(state : Boolean) : Boolean = { def Destroyed_=(state: Boolean): Boolean = {
destroyed = state destroyed = state
Destroyed Destroyed
} }
def Definition : ObjectDefinition def Definition: ObjectDefinition
} }
object PlanetSideGameObject { object PlanetSideGameObject {
def toString(obj : PlanetSideGameObject) : String = { def toString(obj: PlanetSideGameObject): String = {
val guid : String = if(obj.HasGUID) { obj.GUID.toString } else { "NOGUID" } val guid: String = if (obj.HasGUID) { obj.GUID.toString }
else { "NOGUID" }
val P = obj.Position val P = obj.Position
s"[$guid](x,y,z=${P.x%.3f},${P.y%.3f},${P.z%.3f})" s"[$guid](x,y,z=${P.x % .3f},${P.y % .3f},${P.z % .3f})"
} }
} }

View file

@ -2,7 +2,12 @@
package net.psforever.objects package net.psforever.objects
import net.psforever.objects.avatar.LoadoutManager import net.psforever.objects.avatar.LoadoutManager
import net.psforever.objects.definition.{AvatarDefinition, ExoSuitDefinition, ImplantDefinition, SpecialExoSuitDefinition} import net.psforever.objects.definition.{
AvatarDefinition,
ExoSuitDefinition,
ImplantDefinition,
SpecialExoSuitDefinition
}
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit} import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem} import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
@ -16,7 +21,8 @@ import net.psforever.types.{PlanetSideGUID, _}
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.util.{Success, Try} import scala.util.{Success, Try}
class Player(private val core : Avatar) extends PlanetSideServerObject class Player(private val core: Avatar)
extends PlanetSideServerObject
with FactionAffinity with FactionAffinity
with Vitality with Vitality
with ResistanceProfile with ResistanceProfile
@ -25,67 +31,69 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
with ZoneAware { with ZoneAware {
Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead
Destroyed = true //see isAlive Destroyed = true //see isAlive
private var backpack : Boolean = false private var backpack: Boolean = false
private var stamina : Int = 0 private var stamina: Int = 0
private var armor : Int = 0 private var armor: Int = 0
private var capacitor : Float = 0f private var capacitor: Float = 0f
private var capacitorState : CapacitorStateType.Value = CapacitorStateType.Idle private var capacitorState: CapacitorStateType.Value = CapacitorStateType.Idle
private var capacitorLastUsedMillis : Long = 0 private var capacitorLastUsedMillis: Long = 0
private var capacitorLastChargedMillis : Long = 0 private var capacitorLastChargedMillis: Long = 0
private var maxStamina : Int = 100 //does anything affect this? private var maxStamina: Int = 100 //does anything affect this?
private var exosuit : ExoSuitDefinition = GlobalDefinitions.Standard private var exosuit: ExoSuitDefinition = GlobalDefinitions.Standard
private val freeHand : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory) private val freeHand: EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
private val holsters : Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot) private val holsters: Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
private val inventory : GridInventory = GridInventory() private val inventory: GridInventory = GridInventory()
private var drawnSlot : Int = Player.HandsDownSlot private var drawnSlot: Int = Player.HandsDownSlot
private var lastDrawnSlot : Int = Player.HandsDownSlot private var lastDrawnSlot: Int = Player.HandsDownSlot
private var backpackAccess : Option[PlanetSideGUID] = None private var backpackAccess: Option[PlanetSideGUID] = None
private var facingYawUpper : Float = 0f private var facingYawUpper: Float = 0f
private var crouching : Boolean = false private var crouching: Boolean = false
private var jumping : Boolean = false private var jumping: Boolean = false
private var cloaked : Boolean = false private var cloaked: Boolean = false
private var fatigued : Boolean = false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina private var fatigued: Boolean =
private var afk : Boolean = false false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina
private var afk: Boolean = false
private var vehicleSeated : Option[PlanetSideGUID] = None private var vehicleSeated: Option[PlanetSideGUID] = None
Continent = "home2" //the zone id Continent = "home2" //the zone id
var spectator : Boolean = false var spectator: Boolean = false
var silenced : Boolean = false var silenced: Boolean = false
var death_by : Int = 0 var death_by: Int = 0
var lastSeenStreamMessage : Array[Long] = Array.fill[Long](65535)(0L) var lastSeenStreamMessage: Array[Long] = Array.fill[Long](65535)(0L)
var lastShotSeq_time : Int = -1 var lastShotSeq_time: Int = -1
/** From PlanetsideAttributeMessage */ /** From PlanetsideAttributeMessage */
var PlanetsideAttribute : Array[Long] = Array.ofDim(120) var PlanetsideAttribute: Array[Long] = Array.ofDim(120)
var skipStaminaRegenForTurns : Int = 0 var skipStaminaRegenForTurns: Int = 0
Player.SuitSetup(this, exosuit) Player.SuitSetup(this, exosuit)
def CharId : Long = core.CharId def CharId: Long = core.CharId
def Name : String = core.name def Name: String = core.name
def Faction : PlanetSideEmpire.Value = core.faction def Faction: PlanetSideEmpire.Value = core.faction
def Sex : CharacterGender.Value = core.sex def Sex: CharacterGender.Value = core.sex
def Head : Int = core.head def Head: Int = core.head
def Voice : CharacterVoice.Value = core.voice def Voice: CharacterVoice.Value = core.voice
def LFS : Boolean = core.LFS def LFS: Boolean = core.LFS
def isAlive : Boolean = !Destroyed def isAlive: Boolean = !Destroyed
def isBackpack : Boolean = backpack def isBackpack: Boolean = backpack
def Spawn : Boolean = { def Spawn: Boolean = {
if(!isAlive && !isBackpack) { if (!isAlive && !isBackpack) {
Destroyed = false Destroyed = false
Health = Definition.DefaultHealth Health = Definition.DefaultHealth
Stamina = MaxStamina Stamina = MaxStamina
@ -96,66 +104,64 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
isAlive isAlive
} }
def Die : Boolean = { def Die: Boolean = {
Destroyed = true Destroyed = true
Health = 0 Health = 0
Stamina = 0 Stamina = 0
false false
} }
def Revive : Boolean = { def Revive: Boolean = {
Destroyed = false Destroyed = false
Health = Definition.DefaultHealth Health = Definition.DefaultHealth
true true
} }
def Release : Boolean = { def Release: Boolean = {
if(!isAlive) { if (!isAlive) {
backpack = true backpack = true
true true
} } else {
else {
false false
} }
} }
def Stamina : Int = stamina def Stamina: Int = stamina
def Stamina_=(assignStamina : Int) : Int = { def Stamina_=(assignStamina: Int): Int = {
stamina = if(isAlive) { math.min(math.max(0, assignStamina), MaxStamina) } else { 0 } stamina = if (isAlive) { math.min(math.max(0, assignStamina), MaxStamina) }
else { 0 }
Stamina Stamina
} }
def MaxStamina : Int = maxStamina def MaxStamina: Int = maxStamina
def MaxStamina_=(max : Int) : Int = { def MaxStamina_=(max: Int): Int = {
maxStamina = math.min(math.max(0, max), 65535) maxStamina = math.min(math.max(0, max), 65535)
MaxStamina MaxStamina
} }
def Armor : Int = armor def Armor: Int = armor
def Armor_=(assignArmor : Int) : Int = { def Armor_=(assignArmor: Int): Int = {
armor = math.min(math.max(0, assignArmor), MaxArmor) armor = math.min(math.max(0, assignArmor), MaxArmor)
Armor Armor
} }
def MaxArmor : Int = exosuit.MaxArmor def MaxArmor: Int = exosuit.MaxArmor
def Capacitor : Float = capacitor def Capacitor: Float = capacitor
def Capacitor_=(value : Float) : Float = { def Capacitor_=(value: Float): Float = {
val newValue = math.min(math.max(0, value), ExoSuitDef.MaxCapacitor.toFloat) val newValue = math.min(math.max(0, value), ExoSuitDef.MaxCapacitor.toFloat)
if(newValue < capacitor) { if (newValue < capacitor) {
capacitorLastUsedMillis = System.currentTimeMillis() capacitorLastUsedMillis = System.currentTimeMillis()
capacitorLastChargedMillis = 0 capacitorLastChargedMillis = 0
} } else if (newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
else if(newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
capacitorLastChargedMillis = System.currentTimeMillis() capacitorLastChargedMillis = System.currentTimeMillis()
capacitorLastUsedMillis = 0 capacitorLastUsedMillis = 0
} } else if (newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
else if(newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
capacitorLastChargedMillis = 0 capacitorLastChargedMillis = 0
capacitorLastUsedMillis = 0 capacitorLastUsedMillis = 0
capacitorState = CapacitorStateType.Idle capacitorState = CapacitorStateType.Idle
@ -165,8 +171,8 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
capacitor capacitor
} }
def CapacitorState : CapacitorStateType.Value = capacitorState def CapacitorState: CapacitorStateType.Value = capacitorState
def CapacitorState_=(value : CapacitorStateType.Value) : CapacitorStateType.Value = { def CapacitorState_=(value: CapacitorStateType.Value): CapacitorStateType.Value = {
value match { value match {
case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis() case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis()
case CapacitorStateType.Discharging => capacitorLastUsedMillis = System.currentTimeMillis() case CapacitorStateType.Discharging => capacitorLastUsedMillis = System.currentTimeMillis()
@ -180,40 +186,36 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def CapacitorLastUsedMillis = capacitorLastUsedMillis def CapacitorLastUsedMillis = capacitorLastUsedMillis
def CapacitorLastChargedMillis = capacitorLastChargedMillis def CapacitorLastChargedMillis = capacitorLastChargedMillis
def VisibleSlots : Set[Int] = if(exosuit.SuitType == ExoSuitType.MAX) { def VisibleSlots: Set[Int] =
if (exosuit.SuitType == ExoSuitType.MAX) {
Set(0) Set(0)
} } else {
else {
(0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet (0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet
} }
override def Slot(slot : Int) : EquipmentSlot = { override def Slot(slot: Int): EquipmentSlot = {
if(inventory.Offset <= slot && slot <= inventory.LastIndex) { if (inventory.Offset <= slot && slot <= inventory.LastIndex) {
inventory.Slot(slot) inventory.Slot(slot)
} } else if (slot > -1 && slot < 5) {
else if(slot > -1 && slot < 5) {
holsters(slot) holsters(slot)
} } else if (slot == 5) {
else if(slot == 5) {
core.FifthSlot core.FifthSlot
} } else if (slot == Player.FreeHandSlot) {
else if(slot == Player.FreeHandSlot) {
freeHand freeHand
} } else {
else {
OffhandEquipmentSlot.BlockedSlot OffhandEquipmentSlot.BlockedSlot
} }
} }
def Holsters() : Array[EquipmentSlot] = holsters def Holsters(): Array[EquipmentSlot] = holsters
def Inventory : GridInventory = inventory def Inventory: GridInventory = inventory
def Locker : LockerContainer = core.Locker def Locker: LockerContainer = core.Locker
def FifthSlot : EquipmentSlot = core.FifthSlot def FifthSlot: EquipmentSlot = core.FifthSlot
override def Fit(obj : Equipment) : Option[Int] = { override def Fit(obj: Equipment): Option[Int] = {
recursiveHolsterFit(holsters.iterator, obj.Size) match { recursiveHolsterFit(holsters.iterator, obj.Size) match {
case Some(index) => case Some(index) =>
Some(index) Some(index)
@ -222,21 +224,24 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
case Some(index) => case Some(index) =>
Some(index) Some(index)
case None => case None =>
if(freeHand.Equipment.isDefined) { None } else { Some(Player.FreeHandSlot) } if (freeHand.Equipment.isDefined) { None }
else { Some(Player.FreeHandSlot) }
} }
} }
} }
@tailrec private def recursiveHolsterFit(iter : Iterator[EquipmentSlot], objSize : EquipmentSize.Value, index : Int = 0) : Option[Int] = { @tailrec private def recursiveHolsterFit(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
objSize: EquipmentSize.Value,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None None
} } else {
else {
val slot = iter.next val slot = iter.next
if(slot.Equipment.isEmpty && slot.Size.equals(objSize)) { if (slot.Equipment.isEmpty && slot.Size.equals(objSize)) {
Some(index) Some(index)
} } else {
else {
recursiveHolsterFit(iter, objSize, index + 1) recursiveHolsterFit(iter, objSize, index + 1)
} }
} }
@ -244,73 +249,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def FreeHand = freeHand def FreeHand = freeHand
def FreeHand_=(item : Option[Equipment]) : Option[Equipment] = { def FreeHand_=(item: Option[Equipment]): Option[Equipment] = {
if(freeHand.Equipment.isEmpty || item.isEmpty) { if (freeHand.Equipment.isEmpty || item.isEmpty) {
freeHand.Equipment = item freeHand.Equipment = item
} }
FreeHand.Equipment FreeHand.Equipment
} }
override def Find(guid : PlanetSideGUID) : Option[Int] = { override def Find(guid: PlanetSideGUID): Option[Int] = {
findInHolsters(holsters.iterator, guid) findInHolsters(holsters.iterator, guid)
.orElse(inventory.Find(guid)) match { .orElse(inventory.Find(guid)) match {
case Some(index) => case Some(index) =>
Some(index) Some(index)
case None => case None =>
if(freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) { if (freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) {
Some(Player.FreeHandSlot) Some(Player.FreeHandSlot)
} } else {
else {
None None
} }
} }
} }
@tailrec private def findInHolsters(iter : Iterator[EquipmentSlot], guid : PlanetSideGUID, index : Int = 0) : Option[Int] = { @tailrec private def findInHolsters(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
guid: PlanetSideGUID,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None None
} } else {
else {
val slot = iter.next val slot = iter.next
if(slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) { if (slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) {
Some(index) Some(index)
} } else {
else {
findInHolsters(iter, guid, index + 1) findInHolsters(iter, guid, index + 1)
} }
} }
} }
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = { override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
if(-1 < dest && dest < 5) { if (-1 < dest && dest < 5) {
holsters(dest).Equipment match { holsters(dest).Equipment match {
case Some(item) => case Some(item) =>
Success(List(InventoryItem(item, dest))) Success(List(InventoryItem(item, dest)))
case None => case None =>
Success(List()) Success(List())
} }
} } else if (dest == Player.FreeHandSlot) {
else if(dest == Player.FreeHandSlot) {
freeHand.Equipment match { freeHand.Equipment match {
case Some(item) => case Some(item) =>
Success(List(InventoryItem(item, dest))) Success(List(InventoryItem(item, dest)))
case None => case None =>
Success(List()) Success(List())
} }
} } else {
else {
super.Collisions(dest, width, height) super.Collisions(dest, width, height)
} }
} }
def DrawnSlot : Int = drawnSlot def DrawnSlot: Int = drawnSlot
def DrawnSlot_=(slot : Int) : Int = { def DrawnSlot_=(slot: Int): Int = {
if(slot != drawnSlot) { if (slot != drawnSlot) {
if(slot == Player.HandsDownSlot) { if (slot == Player.HandsDownSlot) {
drawnSlot = slot drawnSlot = slot
} } else if (VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
else if(VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
drawnSlot = slot drawnSlot = slot
lastDrawnSlot = slot lastDrawnSlot = slot
} }
@ -318,12 +321,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
DrawnSlot DrawnSlot
} }
def LastDrawnSlot : Int = lastDrawnSlot def LastDrawnSlot: Int = lastDrawnSlot
def ExoSuit : ExoSuitType.Value = exosuit.SuitType def ExoSuit: ExoSuitType.Value = exosuit.SuitType
def ExoSuitDef : ExoSuitDefinition = exosuit def ExoSuitDef: ExoSuitDefinition = exosuit
def ExoSuit_=(suit : ExoSuitType.Value) : Unit = { def ExoSuit_=(suit: ExoSuitType.Value): Unit = {
val eSuit = ExoSuitDefinition.Select(suit, Faction) val eSuit = ExoSuitDefinition.Select(suit, Faction)
exosuit = eSuit exosuit = eSuit
Player.SuitSetup(this, eSuit) Player.SuitSetup(this, eSuit)
@ -340,15 +343,15 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def RadiationShielding = exosuit.RadiationShielding def RadiationShielding = exosuit.RadiationShielding
def EquipmentLoadouts : LoadoutManager = core.EquipmentLoadouts def EquipmentLoadouts: LoadoutManager = core.EquipmentLoadouts
def SquadLoadouts : LoadoutManager = core.SquadLoadouts def SquadLoadouts: LoadoutManager = core.SquadLoadouts
def BEP : Long = core.BEP def BEP: Long = core.BEP
def CEP : Long = core.CEP def CEP: Long = core.CEP
def Certifications : Set[CertificationType.Value] = core.Certifications.toSet def Certifications: Set[CertificationType.Value] = core.Certifications.toSet
/** /**
* What kind of implant is installed into the given slot number? * What kind of implant is installed into the given slot number?
@ -356,71 +359,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param slot the slot number * @param slot the slot number
* @return the tye of implant * @return the tye of implant
*/ */
def Implant(slot : Int) : ImplantType.Value = core.Implant(slot) def Implant(slot: Int): ImplantType.Value = core.Implant(slot)
def ImplantSlot(slot: Int) : ImplantSlot = core.Implants(slot) def ImplantSlot(slot: Int): ImplantSlot = core.Implants(slot)
/** /**
* A read-only `Array` of tuples representing important information about all unlocked implant slots. * A read-only `Array` of tuples representing important information about all unlocked implant slots.
* @return a maximum of three implant types, initialization times, and active flags * @return a maximum of three implant types, initialization times, and active flags
*/ */
def Implants : Array[(ImplantType.Value, Long, Boolean)] = { def Implants: Array[(ImplantType.Value, Long, Boolean)] = {
core.Implants.takeWhile(_.Unlocked).map( implant => { (implant.Implant, implant.MaxTimer, implant.Active) }) core.Implants.takeWhile(_.Unlocked).map(implant => { (implant.Implant, implant.MaxTimer, implant.Active) })
} }
def InstallImplant(implant : ImplantDefinition) : Option[Int] = core.InstallImplant(implant) def InstallImplant(implant: ImplantDefinition): Option[Int] = core.InstallImplant(implant)
def UninstallImplant(implant : ImplantType.Value) : Option[Int] = core.UninstallImplant(implant) def UninstallImplant(implant: ImplantType.Value): Option[Int] = core.UninstallImplant(implant)
def ResetAllImplants() : Unit = core.ResetAllImplants() def ResetAllImplants(): Unit = core.ResetAllImplants()
def FacingYawUpper : Float = facingYawUpper def FacingYawUpper: Float = facingYawUpper
def FacingYawUpper_=(facing : Float) : Float = { def FacingYawUpper_=(facing: Float): Float = {
facingYawUpper = facing facingYawUpper = facing
FacingYawUpper FacingYawUpper
} }
def Crouching : Boolean = crouching def Crouching: Boolean = crouching
def Crouching_=(crouched : Boolean) : Boolean = { def Crouching_=(crouched: Boolean): Boolean = {
crouching = crouched crouching = crouched
Crouching Crouching
} }
def Jumping : Boolean = jumping def Jumping: Boolean = jumping
def Jumping_=(jumped : Boolean) : Boolean = { def Jumping_=(jumped: Boolean): Boolean = {
jumping = jumped jumping = jumped
Jumping Jumping
} }
def Cloaked : Boolean = cloaked def Cloaked: Boolean = cloaked
def Cloaked_=(isCloaked : Boolean) : Boolean = { def Cloaked_=(isCloaked: Boolean): Boolean = {
cloaked = isCloaked cloaked = isCloaked
Cloaked Cloaked
} }
def Fatigued : Boolean = fatigued def Fatigued: Boolean = fatigued
def Fatigued_=(isFatigued : Boolean) : Boolean = { def Fatigued_=(isFatigued: Boolean): Boolean = {
fatigued = isFatigued fatigued = isFatigued
Fatigued Fatigued
} }
def AwayFromKeyboard : Boolean = afk def AwayFromKeyboard: Boolean = afk
def AwayFromKeyboard_=(away : Boolean) : Boolean = { def AwayFromKeyboard_=(away: Boolean): Boolean = {
afk = away afk = away
AwayFromKeyboard AwayFromKeyboard
} }
def PersonalStyleFeatures : Option[Cosmetics] = core.PersonalStyleFeatures def PersonalStyleFeatures: Option[Cosmetics] = core.PersonalStyleFeatures
def AddToPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = { def AddToPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
val original = core.PersonalStyleFeatures val original = core.PersonalStyleFeatures
if(DetailedCharacterData.isBR24(core.BEP)) { if (DetailedCharacterData.isBR24(core.BEP)) {
core.PersonalStyleFeatures = original match { core.PersonalStyleFeatures = original match {
case Some(cosmetic) => case Some(cosmetic) =>
cosmetic + value cosmetic + value
@ -428,13 +431,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
Cosmetics(value) Cosmetics(value)
} }
(original, core.PersonalStyleFeatures) (original, core.PersonalStyleFeatures)
} } else {
else {
(None, None) (None, None)
} }
} }
def RemoveFromPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = { def RemoveFromPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
val original = core.PersonalStyleFeatures val original = core.PersonalStyleFeatures
original match { original match {
case Some(cosmetics) => case Some(cosmetics) =>
@ -444,35 +446,32 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
} }
} }
private def BasicFeatureToggle(feature : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = core.PersonalStyleFeatures match { private def BasicFeatureToggle(feature: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) =
case Some(c : Cosmetics) =>
if(c.Styles.contains(feature)) {
RemoveFromPersonalStyle(feature)
}
else {
AddToPersonalStyle(feature)
}
case None =>
AddToPersonalStyle(feature)
}
def ToggleHelmet : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
def ToggleShades : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
def ToggleEarpiece : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
def ToggleHat : (Option[Cosmetics], Option[Cosmetics]) = {
core.PersonalStyleFeatures match { core.PersonalStyleFeatures match {
case Some(c : Cosmetics) => case Some(c: Cosmetics) =>
if(c.Styles.contains(PersonalStyle.BrimmedCap)) { if (c.Styles.contains(feature)) {
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1, RemoveFromPersonalStyle(feature)
AddToPersonalStyle(PersonalStyle.Beret)._2) } else {
AddToPersonalStyle(feature)
} }
else if(c.Styles.contains(PersonalStyle.Beret)) { case None =>
AddToPersonalStyle(feature)
}
def ToggleHelmet: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
def ToggleShades: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
def ToggleEarpiece: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
def ToggleHat: (Option[Cosmetics], Option[Cosmetics]) = {
core.PersonalStyleFeatures match {
case Some(c: Cosmetics) =>
if (c.Styles.contains(PersonalStyle.BrimmedCap)) {
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1, AddToPersonalStyle(PersonalStyle.Beret)._2)
} else if (c.Styles.contains(PersonalStyle.Beret)) {
RemoveFromPersonalStyle(PersonalStyle.Beret) RemoveFromPersonalStyle(PersonalStyle.Beret)
} } else {
else {
AddToPersonalStyle(PersonalStyle.BrimmedCap) AddToPersonalStyle(PersonalStyle.BrimmedCap)
} }
case None => case None =>
@ -480,96 +479,99 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
} }
} }
private var usingSpecial : SpecialExoSuitDefinition.Mode.Value=>SpecialExoSuitDefinition.Mode.Value = DefaultUsingSpecial private var usingSpecial: SpecialExoSuitDefinition.Mode.Value => SpecialExoSuitDefinition.Mode.Value =
DefaultUsingSpecial
private var gettingSpecial : ()=>SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial private var gettingSpecial: () => SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial
private def ChangeSpecialAbility() : Unit = { private def ChangeSpecialAbility(): Unit = {
if(ExoSuit == ExoSuitType.MAX) { if (ExoSuit == ExoSuitType.MAX) {
gettingSpecial = MAXGettingSpecial gettingSpecial = MAXGettingSpecial
usingSpecial = Faction match { usingSpecial = Faction match {
case PlanetSideEmpire.TR => UsingAnchorsOrOverdrive case PlanetSideEmpire.TR => UsingAnchorsOrOverdrive
case PlanetSideEmpire.NC => UsingShield case PlanetSideEmpire.NC => UsingShield
case _ => DefaultUsingSpecial case _ => DefaultUsingSpecial
} }
} } else {
else {
usingSpecial = DefaultUsingSpecial usingSpecial = DefaultUsingSpecial
gettingSpecial = DefaultGettingSpecial gettingSpecial = DefaultGettingSpecial
} }
} }
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() } def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() }
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = usingSpecial(state) def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
usingSpecial(state)
private def DefaultUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal private def DefaultUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
SpecialExoSuitDefinition.Mode.Normal
private def UsingAnchorsOrOverdrive(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = { private def UsingAnchorsOrOverdrive(
state: SpecialExoSuitDefinition.Mode.Value
): SpecialExoSuitDefinition.Mode.Value = {
import SpecialExoSuitDefinition.Mode._ import SpecialExoSuitDefinition.Mode._
val curr = UsingSpecial val curr = UsingSpecial
val next = if(curr == Normal) { val next = if (curr == Normal) {
if(state == Anchored || state == Overdrive) { if (state == Anchored || state == Overdrive) {
state state
} } else {
else {
Normal Normal
} }
} } else if (state == Normal) {
else if(state == Normal) {
Normal Normal
} } else {
else {
curr curr
} }
MAXUsingSpecial(next) MAXUsingSpecial(next)
} }
private def UsingShield(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = { private def UsingShield(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
import SpecialExoSuitDefinition.Mode._ import SpecialExoSuitDefinition.Mode._
val curr = UsingSpecial val curr = UsingSpecial
val next = if(curr == Normal) { val next = if (curr == Normal) {
if(state == Shielded) { if (state == Shielded) {
state state
} } else {
else {
Normal Normal
} }
} } else if (state == Normal) {
else if(state == Normal) {
Normal Normal
} } else {
else {
curr curr
} }
MAXUsingSpecial(next) MAXUsingSpecial(next)
} }
private def DefaultGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal private def DefaultGettingSpecial(): SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
private def MAXUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = exosuit match { private def MAXUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
case obj : SpecialExoSuitDefinition => exosuit match {
case obj: SpecialExoSuitDefinition =>
obj.UsingSpecial = state obj.UsingSpecial = state
case _ => case _ =>
SpecialExoSuitDefinition.Mode.Normal SpecialExoSuitDefinition.Mode.Normal
} }
private def MAXGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = exosuit match { private def MAXGettingSpecial(): SpecialExoSuitDefinition.Mode.Value =
case obj : SpecialExoSuitDefinition => exosuit match {
case obj: SpecialExoSuitDefinition =>
obj.UsingSpecial obj.UsingSpecial
case _ => case _ =>
SpecialExoSuitDefinition.Mode.Normal SpecialExoSuitDefinition.Mode.Normal
} }
def isAnchored : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored def isAnchored: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored
def isOverdrived : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive def isOverdrived: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive
def isShielded : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded def isShielded: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded
def AccessingBackpack : Option[PlanetSideGUID] = backpackAccess def AccessingBackpack: Option[PlanetSideGUID] = backpackAccess
def AccessingBackpack_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = { def AccessingBackpack_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
AccessingBackpack = Some(guid) AccessingBackpack = Some(guid)
} }
@ -579,12 +581,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param guid the player who wishes to access the backpack * @param guid the player who wishes to access the backpack
* @return the player who is currently allowed to access the backpack * @return the player who is currently allowed to access the backpack
*/ */
def AccessingBackpack_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def AccessingBackpack_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
guid match { guid match {
case None => case None =>
backpackAccess = None backpackAccess = None
case Some(player) => case Some(player) =>
if(isBackpack && backpackAccess.isEmpty) { if (isBackpack && backpackAccess.isEmpty) {
backpackAccess = Some(player) backpackAccess = Some(player)
} }
} }
@ -596,58 +598,60 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param player a player attempting to access this backpack * @param player a player attempting to access this backpack
* @return `true`, if the `player` is permitted access; `false`, otherwise * @return `true`, if the `player` is permitted access; `false`, otherwise
*/ */
def CanAccessBackpack(player : Player) : Boolean = { def CanAccessBackpack(player: Player): Boolean = {
isBackpack && (backpackAccess.isEmpty || backpackAccess.contains(player.GUID)) isBackpack && (backpackAccess.isEmpty || backpackAccess.contains(player.GUID))
} }
def FirstTimeEvents : List[String] = core.FirstTimeEvents def FirstTimeEvents: List[String] = core.FirstTimeEvents
def VehicleSeated : Option[PlanetSideGUID] = vehicleSeated def VehicleSeated: Option[PlanetSideGUID] = vehicleSeated
def VehicleSeated_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleSeated_=(Some(guid)) def VehicleSeated_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
def VehicleSeated_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def VehicleSeated_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
vehicleSeated = guid vehicleSeated = guid
VehicleSeated VehicleSeated
} }
def VehicleOwned : Option[PlanetSideGUID] = core.VehicleOwned def VehicleOwned: Option[PlanetSideGUID] = core.VehicleOwned
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid)) def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = core.VehicleOwned_=(guid) def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = core.VehicleOwned_=(guid)
def GetLastUsedTime(code : Int) : Long = core.GetLastUsedTime(code) def GetLastUsedTime(code: Int): Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code : ExoSuitType.Value) : Long = core.GetLastUsedTime(code) def GetLastUsedTime(code: ExoSuitType.Value): Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = core.GetLastUsedTime(code, subtype) def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = core.GetLastUsedTime(code, subtype)
def SetLastUsedTime(code : Int, time : Long) : Unit = core.SetLastUsedTime(code, time) def SetLastUsedTime(code: Int, time: Long): Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code : ExoSuitType.Value): Unit = core.SetLastUsedTime(code) def SetLastUsedTime(code: ExoSuitType.Value): Unit = core.SetLastUsedTime(code)
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = core.SetLastUsedTime(code, time) def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int): Unit = core.SetLastUsedTime(code, subtype) def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Unit = core.SetLastUsedTime(code, subtype)
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = core.SetLastUsedTime(code, subtype, time) def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit =
core.SetLastUsedTime(code, subtype, time)
def GetLastPurchaseTime(code : Int) : Long = core.GetLastPurchaseTime(code) def GetLastPurchaseTime(code: Int): Long = core.GetLastPurchaseTime(code)
def SetLastPurchaseTime(code : Int, time : Long) : Unit = core.SetLastPurchaseTime(code, time) def SetLastPurchaseTime(code: Int, time: Long): Unit = core.SetLastPurchaseTime(code, time)
def ObjectTypeNameReference(id : Long) : String = core.ObjectTypeNameReference(id) def ObjectTypeNameReference(id: Long): String = core.ObjectTypeNameReference(id)
def ObjectTypeNameReference(id : Long, name : String) : String = core.ObjectTypeNameReference(id, name) def ObjectTypeNameReference(id: Long, name: String): String = core.ObjectTypeNameReference(id, name)
def DamageModel = exosuit.asInstanceOf[DamageResistanceModel] def DamageModel = exosuit.asInstanceOf[DamageResistanceModel]
def Definition : AvatarDefinition = core.Definition def Definition: AvatarDefinition = core.Definition
def canEqual(other: Any): Boolean = other.isInstanceOf[Player] def canEqual(other: Any): Boolean = other.isInstanceOf[Player]
override def equals(other : Any) : Boolean = other match { override def equals(other: Any): Boolean =
other match {
case that: Player => case that: Player =>
(that canEqual this) && (that canEqual this) &&
core == that.core core == that.core
@ -655,35 +659,35 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
false false
} }
override def hashCode() : Int = { override def hashCode(): Int = {
core.hashCode() core.hashCode()
} }
override def toString : String = Player.toString(this) override def toString: String = Player.toString(this)
} }
object Player { object Player {
final val LockerSlot : Int = 5 final val LockerSlot: Int = 5
final val FreeHandSlot : Int = 250 final val FreeHandSlot: Int = 250
final val HandsDownSlot : Int = 255 final val HandsDownSlot: Int = 255
final case class Die() final case class Die()
final case class ImplantActivation(slot : Int, status : Int) final case class ImplantActivation(slot: Int, status: Int)
final case class ImplantInitializationStart(slot : Int) final case class ImplantInitializationStart(slot: Int)
final case class UninitializeImplant(slot : Int) final case class UninitializeImplant(slot: Int)
final case class ImplantInitializationComplete(slot : Int) final case class ImplantInitializationComplete(slot: Int)
final case class StaminaRegen() final case class StaminaRegen()
final case class StaminaChanged(currentStamina : Option[Int] = None) final case class StaminaChanged(currentStamina: Option[Int] = None)
object StaminaChanged { object StaminaChanged {
def apply(amount : Int) : StaminaChanged = StaminaChanged(Some(amount)) def apply(amount: Int): StaminaChanged = StaminaChanged(Some(amount))
} }
def apply(core : Avatar) : Player = { def apply(core: Avatar): Player = {
new Player(core) new Player(core)
} }
private def SuitSetup(player : Player, eSuit : ExoSuitDefinition) : Unit = { private def SuitSetup(player: Player, eSuit: ExoSuitDefinition): Unit = {
//inventory //inventory
player.Inventory.Clear() player.Inventory.Clear()
player.Inventory.Resize(eSuit.InventoryScale.Width, eSuit.InventoryScale.Height) player.Inventory.Resize(eSuit.InventoryScale.Width, eSuit.InventoryScale.Height)
@ -692,34 +696,35 @@ object Player {
(0 until 5).foreach(index => { player.Slot(index).Size = eSuit.Holster(index) }) (0 until 5).foreach(index => { player.Slot(index).Size = eSuit.Holster(index) })
} }
def Respawn(player : Player) : Player = { def Respawn(player: Player): Player = {
if(player.Release) { if (player.Release) {
val obj = new Player(player.core) val obj = new Player(player.core)
obj.Continent = player.Continent obj.Continent = player.Continent
obj obj
} } else {
else {
player player
} }
} }
def GetHackLevel(player : Player): Int = { def GetHackLevel(player: Player): Int = {
if(player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(CertificationType.ElectronicsExpert)) { if (
player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(
CertificationType.ElectronicsExpert
)
) {
3 3
} } else if (player.Certifications.contains(CertificationType.AdvancedHacking)) {
else if(player.Certifications.contains(CertificationType.AdvancedHacking)) {
2 2
} } else if (player.Certifications.contains(CertificationType.Hacking)) {
else if (player.Certifications.contains(CertificationType.Hacking)) {
1 1
} } else {
else {
0 0
} }
} }
def toString(obj : Player) : String = { def toString(obj: Player): String = {
val guid = if(obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" } else { "" } val guid = if (obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" }
else { "" }
s"${obj.core}$guid ${obj.Health}/${obj.MaxHealth} ${obj.Armor}/${obj.MaxArmor}" s"${obj.core}$guid ${obj.Health}/${obj.MaxHealth} ${obj.Armor}/${obj.MaxArmor}"
} }
} }

View file

@ -25,17 +25,21 @@ object Players {
* @return `true`, if the next cycle of progress should occur; * @return `true`, if the next cycle of progress should occur;
* `false`, otherwise * `false`, otherwise
*/ */
def RevivingTickAction(target : Player, user : Player, item : Tool)(progress : Float) : Boolean = { def RevivingTickAction(target: Player, user: Player, item: Tool)(progress: Float): Boolean = {
if(!target.isAlive && !target.isBackpack && if (
!target.isAlive && !target.isBackpack &&
user.isAlive && !user.isMoving && user.isAlive && !user.isMoving &&
user.Slot(user.DrawnSlot).Equipment.contains(item) && item.Magazine >= 25 && user.Slot(user.DrawnSlot).Equipment.contains(item) && item.Magazine >= 25 &&
Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance) { Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance
) {
val events = target.Zone.AvatarEvents val events = target.Zone.AvatarEvents
val uname = user.Name val uname = user.Name
events ! AvatarServiceMessage(uname, AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt))) events ! AvatarServiceMessage(
uname,
AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt))
)
true true
} } else {
else {
false false
} }
} }
@ -48,11 +52,17 @@ object Players {
* @param medic the name of the player doing the reviving * @param medic the name of the player doing the reviving
* @param item the tool being used to revive the target player * @param item the tool being used to revive the target player
*/ */
def FinishRevivingPlayer(target : Player, medic : String, item : Tool)() : Unit = { def FinishRevivingPlayer(target: Player, medic: String, item: Tool)(): Unit = {
val name = target.Name val name = target.Name
log.info(s"$medic had revived $name") log.info(s"$medic had revived $name")
val magazine = item.Discharge(Some(25)) val magazine = item.Discharge(Some(25))
target.Zone.AvatarEvents ! AvatarServiceMessage(medic, AvatarAction.SendResponse(Service.defaultPlayerGUID, InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine))) target.Zone.AvatarEvents ! AvatarServiceMessage(
medic,
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine)
)
)
target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID)) target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID))
} }
@ -64,11 +74,14 @@ object Players {
* @param list a persistent `List` of `Equipment` in the holster slots * @param list a persistent `List` of `Equipment` in the holster slots
* @return a `List` of `Equipment` in the holster slots * @return a `List` of `Equipment` in the holster slots
*/ */
@tailrec def clearHolsters(iter : Iterator[EquipmentSlot], index : Int = 0, list : List[InventoryItem] = Nil) : List[InventoryItem] = { @tailrec def clearHolsters(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
index: Int = 0,
list: List[InventoryItem] = Nil
): List[InventoryItem] = {
if (!iter.hasNext) {
list list
} } else {
else {
val slot = iter.next val slot = iter.next
slot.Equipment match { slot.Equipment match {
case Some(equipment) => case Some(equipment) =>
@ -88,13 +101,12 @@ object Players {
* @param list a `List` of all `Equipment` that is not yet assigned to a holster slot or an inventory slot * @param list a `List` of all `Equipment` that is not yet assigned to a holster slot or an inventory slot
* @return the `List` of all `Equipment` not yet assigned to a holster slot or an inventory slot * @return the `List` of all `Equipment` not yet assigned to a holster slot or an inventory slot
*/ */
@tailrec def fillEmptyHolsters(iter : Iterator[EquipmentSlot], list : List[InventoryItem]) : List[InventoryItem] = { @tailrec def fillEmptyHolsters(iter: Iterator[EquipmentSlot], list: List[InventoryItem]): List[InventoryItem] = {
if(!iter.hasNext) { if (!iter.hasNext) {
list list
} } else {
else {
val slot = iter.next val slot = iter.next
if(slot.Equipment.isEmpty) { if (slot.Equipment.isEmpty) {
list.find(item => item.obj.Size == slot.Size) match { list.find(item => item.obj.Size == slot.Size) match {
case Some(obj) => case Some(obj) =>
val index = list.indexOf(obj) val index = list.indexOf(obj)
@ -103,14 +115,13 @@ object Players {
case None => case None =>
fillEmptyHolsters(iter, list) fillEmptyHolsters(iter, list)
} }
} } else {
else {
fillEmptyHolsters(iter, list) fillEmptyHolsters(iter, list)
} }
} }
} }
def CertificationToUseExoSuit(player : Player, exosuit : ExoSuitType.Value, subtype : Int) : Boolean = { def CertificationToUseExoSuit(player: Player, exosuit: ExoSuitType.Value, subtype: Int): Boolean = {
ExoSuitDefinition.Select(exosuit, player.Faction).Permissions match { ExoSuitDefinition.Select(exosuit, player.Faction).Permissions match {
case Nil => case Nil =>
true true

View file

@ -19,32 +19,32 @@ import services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._ import scala.concurrent.duration._
class SensorDeployable(cdef : SensorDeployableDefinition) extends ComplexDeployable(cdef) class SensorDeployable(cdef: SensorDeployableDefinition) extends ComplexDeployable(cdef) with Hackable with JammableUnit
with Hackable
with JammableUnit
class SensorDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) { class SensorDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
Name = "sensor_deployable" Name = "sensor_deployable"
DeployCategory = DeployableCategory.Sensors DeployCategory = DeployableCategory.Sensors
Model = StandardResolutions.SimpleDeployables Model = StandardResolutions.SimpleDeployables
Packet = new SmallDeployableConverter Packet = new SmallDeployableConverter
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor =
context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context) SimpleDeployableDefinition.SimpleUninitialize(obj, context)
} }
} }
object SensorDeployableDefinition { object SensorDeployableDefinition {
def apply(dtype : DeployedItem.Value) : SensorDeployableDefinition = { def apply(dtype: DeployedItem.Value): SensorDeployableDefinition = {
new SensorDeployableDefinition(dtype.id) new SensorDeployableDefinition(dtype.id)
} }
} }
class SensorDeployableControl(sensor : SensorDeployable) extends Actor class SensorDeployableControl(sensor: SensorDeployable)
extends Actor
with JammableBehavior with JammableBehavior
with DamageableEntity with DamageableEntity
with RepairableEntity { with RepairableEntity {
@ -52,49 +52,64 @@ class SensorDeployableControl(sensor : SensorDeployable) extends Actor
def DamageableObject = sensor def DamageableObject = sensor
def RepairableObject = sensor def RepairableObject = sensor
def receive : Receive = jammableBehavior def receive: Receive =
jammableBehavior
.orElse(takesDamage) .orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser) .orElse(canBeRepairedByNanoDispenser)
.orElse { .orElse {
case _ => ; case _ => ;
} }
override protected def DamageLog(msg : String) : Unit = { } override protected def DamageLog(msg: String): Unit = {}
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = { override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause) super.DestructionAwareness(target, cause)
SensorDeployableControl.DestructionAwareness(sensor, PlanetSideGUID(0)) SensorDeployableControl.DestructionAwareness(sensor, PlanetSideGUID(0))
} }
override def StartJammeredSound(target : Any, dur : Int) : Unit = target match { override def StartJammeredSound(target: Any, dur: Int): Unit =
case obj : PlanetSideServerObject if !jammedSound => target match {
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1)) case obj: PlanetSideServerObject if !jammedSound =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1)
)
super.StartJammeredSound(obj, dur) super.StartJammeredSound(obj, dur)
case _ => ; case _ => ;
} }
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match { override def StartJammeredStatus(target: Any, dur: Int): Unit =
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed => target match {
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
val zone = obj.Zone val zone = obj.Zone
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000)) zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000)
)
super.StartJammeredStatus(obj, dur) super.StartJammeredStatus(obj, dur)
case _ => ; case _ => ;
} }
override def CancelJammeredSound(target : Any) : Unit = { override def CancelJammeredSound(target: Any): Unit = {
target match { target match {
case obj : PlanetSideServerObject if jammedSound => case obj: PlanetSideServerObject if jammedSound =>
val zone = obj.Zone val zone = obj.Zone
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0)) zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0)
)
case _ => ; case _ => ;
} }
super.CancelJammeredSound(target) super.CancelJammeredSound(target)
} }
override def CancelJammeredStatus(target : Any) : Unit = { override def CancelJammeredStatus(target: Any): Unit = {
target match { target match {
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed => case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
sensor.Zone.LocalEvents ! LocalServiceMessage(sensor.Zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000)) sensor.Zone.LocalEvents ! LocalServiceMessage(
sensor.Zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000)
)
case _ => ; case _ => ;
} }
super.CancelJammeredStatus(target) super.CancelJammeredStatus(target)
@ -102,15 +117,17 @@ class SensorDeployableControl(sensor : SensorDeployable) extends Actor
} }
object SensorDeployableControl { object SensorDeployableControl {
/** /**
* na * na
* @param target na * @param target na
* @param attribution na * @param attribution na
*/ */
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = { def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
Deployables.AnnounceDestroyDeployable(target, Some(1 seconds)) Deployables.AnnounceDestroyDeployable(target, Some(1 seconds))
val zone = target.Zone val zone = target.Zone
zone.LocalEvents ! LocalServiceMessage(zone.Id, zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", target.GUID, false, 1000) LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", target.GUID, false, 1000)
) )
//position the explosion effect near the bulky area of the sensor stalk //position the explosion effect near the bulky area of the sensor stalk
@ -125,7 +142,8 @@ object SensorDeployableControl {
pos.z + math.cos(yRadians).toFloat * 0.875f pos.z + math.cos(yRadians).toFloat * 0.875f
) )
} }
zone.LocalEvents ! LocalServiceMessage(zone.Id, zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectLocation(Service.defaultPlayerGUID, "motion_sensor_destroyed", explosionPos, ang) LocalAction.TriggerEffectLocation(Service.defaultPlayerGUID, "motion_sensor_destroyed", explosionPos, ang)
) )
//TODO replaced by an alternate model (charred stub)? //TODO replaced by an alternate model (charred stub)?

View file

@ -17,7 +17,8 @@ import net.psforever.types.PlanetSideGUID
import services.Service import services.Service
import services.vehicle.{VehicleAction, VehicleServiceMessage} import services.vehicle.{VehicleAction, VehicleServiceMessage}
class ShieldGeneratorDeployable(cdef : ShieldGeneratorDefinition) extends ComplexDeployable(cdef) class ShieldGeneratorDeployable(cdef: ShieldGeneratorDefinition)
extends ComplexDeployable(cdef)
with Hackable with Hackable
with JammableUnit with JammableUnit
@ -25,25 +26,28 @@ class ShieldGeneratorDefinition extends ComplexDeployableDefinition(240) {
Packet = new ShieldGeneratorConverter Packet = new ShieldGeneratorConverter
DeployCategory = DeployableCategory.ShieldGenerators DeployCategory = DeployableCategory.ShieldGenerators
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor =
context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context) SimpleDeployableDefinition.SimpleUninitialize(obj, context)
} }
} }
class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor class ShieldGeneratorControl(gen: ShieldGeneratorDeployable)
extends Actor
with JammableBehavior with JammableBehavior
with DamageableEntity with DamageableEntity
with RepairableEntity { with RepairableEntity {
def JammableObject = gen def JammableObject = gen
def DamageableObject = gen def DamageableObject = gen
def RepairableObject = gen def RepairableObject = gen
private var handleDamageToShields : Boolean = false private var handleDamageToShields: Boolean = false
def receive : Receive = jammableBehavior def receive: Receive =
jammableBehavior
.orElse(takesDamage) .orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser) .orElse(canBeRepairedByNanoDispenser)
.orElse { .orElse {
@ -59,17 +63,19 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
* @param player the user of the nano dispenser tool * @param player the user of the nano dispenser tool
* @param item the nano dispenser tool * @param item the nano dispenser tool
*/ */
override def CanBeRepairedByNanoDispenser(player : Player, item : Tool) : Unit = { override def CanBeRepairedByNanoDispenser(player: Player, item: Tool): Unit = {
if(gen.CanRepair) { if (gen.CanRepair) {
super.CanBeRepairedByNanoDispenser(player, item) super.CanBeRepairedByNanoDispenser(player, item)
} } else if (!gen.Destroyed) {
else if(!gen.Destroyed) {
//TODO reinforced shield upgrade not implemented yet //TODO reinforced shield upgrade not implemented yet
//TODO ammunition supply upgrade not implemented yet //TODO ammunition supply upgrade not implemented yet
} }
} }
override protected def PerformDamage(target : Damageable.Target, applyDamageTo : ResolutionCalculations.Output) : Unit = { override protected def PerformDamage(
target: Damageable.Target,
applyDamageTo: ResolutionCalculations.Output
): Unit = {
val originalHealth = gen.Health val originalHealth = gen.Health
val originalShields = gen.Shields val originalShields = gen.Shields
val cause = applyDamageTo(target) val cause = applyDamageTo(target)
@ -78,25 +84,27 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
val damageToHealth = originalHealth - health val damageToHealth = originalHealth - health
val damageToShields = originalShields - shields val damageToShields = originalShields - shields
val damage = damageToHealth + damageToShields val damage = damageToHealth + damageToShields
if(WillAffectTarget(target, damage, cause)) { if (WillAffectTarget(target, damage, cause)) {
target.History(cause) target.History(cause)
DamageLog(target,s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields") DamageLog(
target,
s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields"
)
handleDamageToShields = damageToShields > 0 handleDamageToShields = damageToShields > 0
HandleDamage(target, cause, damageToHealth) HandleDamage(target, cause, damageToHealth)
} } else {
else {
gen.Health = originalHealth gen.Health = originalHealth
gen.Shields = originalShields gen.Shields = originalShields
} }
} }
override protected def DamageAwareness(target : Damageable.Target, cause : ResolvedProjectile, amount : Int) : Unit = { override protected def DamageAwareness(target: Damageable.Target, cause: ResolvedProjectile, amount: Int): Unit = {
super.DamageAwareness(target, cause, amount) super.DamageAwareness(target, cause, amount)
ShieldGeneratorControl.DamageAwareness(gen, cause, handleDamageToShields) ShieldGeneratorControl.DamageAwareness(gen, cause, handleDamageToShields)
handleDamageToShields = false handleDamageToShields = false
} }
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = { override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause) super.DestructionAwareness(target, cause)
ShieldGeneratorControl.DestructionAwareness(gen, PlanetSideGUID(0)) ShieldGeneratorControl.DestructionAwareness(gen, PlanetSideGUID(0))
} }
@ -105,21 +113,28 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
while the shield generator is technically a supported jammable target, how that works is currently unknown while the shield generator is technically a supported jammable target, how that works is currently unknown
check the object definition for proper feature activation check the object definition for proper feature activation
*/ */
override def StartJammeredSound(target : Any, dur : Int) : Unit = { } override def StartJammeredSound(target: Any, dur: Int): Unit = {}
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match { override def StartJammeredStatus(target: Any, dur: Int): Unit =
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed => target match {
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)) case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)
)
super.StartJammeredStatus(obj, dur) super.StartJammeredStatus(obj, dur)
case _ => ; case _ => ;
} }
override def CancelJammeredSound(target : Any) : Unit = { } override def CancelJammeredSound(target: Any): Unit = {}
override def CancelJammeredStatus(target : Any) : Unit = { override def CancelJammeredStatus(target: Any): Unit = {
target match { target match {
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed => case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0)) obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0)
)
case _ => ; case _ => ;
} }
super.CancelJammeredStatus(target) super.CancelJammeredStatus(target)
@ -127,17 +142,21 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
} }
object ShieldGeneratorControl { object ShieldGeneratorControl {
/** /**
* na * na
* @param target na * @param target na
* @param cause na * @param cause na
* @param damageToShields na * @param damageToShields na
*/ */
def DamageAwareness(target : ShieldGeneratorDeployable, cause : ResolvedProjectile, damageToShields : Boolean) : Unit = { def DamageAwareness(target: ShieldGeneratorDeployable, cause: ResolvedProjectile, damageToShields: Boolean): Unit = {
//shields //shields
if(damageToShields) { if (damageToShields) {
val zone = target.Zone val zone = target.Zone
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields)) zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields)
)
} }
} }
@ -146,7 +165,7 @@ object ShieldGeneratorControl {
* @param target na * @param target na
* @param attribution na * @param attribution na
*/ */
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = { def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
Deployables.AnnounceDestroyDeployable(target, None) Deployables.AnnounceDestroyDeployable(target, None)
} }
} }

View file

@ -4,12 +4,12 @@ package net.psforever.objects
import net.psforever.objects.definition.SimpleItemDefinition import net.psforever.objects.definition.SimpleItemDefinition
import net.psforever.objects.equipment.Equipment import net.psforever.objects.equipment.Equipment
class SimpleItem(private val simpDef : SimpleItemDefinition) extends Equipment { class SimpleItem(private val simpDef: SimpleItemDefinition) extends Equipment {
def Definition : SimpleItemDefinition = simpDef def Definition: SimpleItemDefinition = simpDef
} }
object SimpleItem { object SimpleItem {
def apply(simpDef : SimpleItemDefinition) : SimpleItem = { def apply(simpDef: SimpleItemDefinition): SimpleItem = {
new SimpleItem(simpDef) new SimpleItem(simpDef)
} }
} }

View file

@ -8,27 +8,31 @@ import net.psforever.types.{PlanetSideGUID, Vector3}
import scala.collection.mutable import scala.collection.mutable
trait SpawnPoint { trait SpawnPoint {
psso : PlanetSideServerObject => psso: PlanetSideServerObject =>
/** /**
* An element of the contract of `PlanetSideServerObject`; * An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting. * but, this makes it visible to a `SpawnPoint` object without casting.
* @see `Identifiable.GUID` * @see `Identifiable.GUID`
*/ */
def GUID : PlanetSideGUID def GUID: PlanetSideGUID
/** /**
* An element of the contract of `PlanetSideServerObject`; * An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting. * but, this makes it visible to a `SpawnPoint` object without casting.
* @see `WorldEntity.GUID` * @see `WorldEntity.GUID`
* @see `SpecificPoint` * @see `SpecificPoint`
*/ */
def Position : Vector3 def Position: Vector3
/** /**
* An element of the contract of `PlanetSideServerObject`; * An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting. * but, this makes it visible to a `SpawnPoint` object without casting.
* @see `WorldEntity.GUID` * @see `WorldEntity.GUID`
* @see `SpecificPoint` * @see `SpecificPoint`
*/ */
def Orientation : Vector3 def Orientation: Vector3
/** /**
* An element of an unspoken contract with `Amenity`. * An element of an unspoken contract with `Amenity`.
* While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class, * While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class,
@ -36,16 +40,17 @@ trait SpawnPoint {
* This should generally be themselves. * This should generally be themselves.
* @see `Amenity.Owner` * @see `Amenity.Owner`
*/ */
def Owner : PlanetSideServerObject def Owner: PlanetSideServerObject
/** /**
* An element of the contract of `PlanetSideServerObject`; * An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting. * but, this makes it visible to a `SpawnPoint` object without casting.
* @see `PlanetSideGameObject.Definition` * @see `PlanetSideGameObject.Definition`
* @see `SpecificPoint` * @see `SpecificPoint`
*/ */
def Definition : ObjectDefinition with SpawnPointDefinition def Definition: ObjectDefinition with SpawnPointDefinition
def Offline : Boolean = psso.Destroyed def Offline: Boolean = psso.Destroyed
/** /**
* Determine a specific position and orientation in which to spawn the target. * Determine a specific position and orientation in which to spawn the target.
@ -53,9 +58,9 @@ trait SpawnPoint {
* the first represents the game world position of spawning; * the first represents the game world position of spawning;
* the second represents the game world direction of spawning * the second represents the game world direction of spawning
*/ */
def SpecificPoint(target : PlanetSideGameObject) : (Vector3, Vector3) = { def SpecificPoint(target: PlanetSideGameObject): (Vector3, Vector3) = {
psso.Definition match { psso.Definition match {
case d : SpawnPointDefinition => case d: SpawnPointDefinition =>
d.SpecificPoint(this, target) d.SpecificPoint(this, target)
case _ => case _ =>
SpawnPoint.Default(this, target) SpawnPoint.Default(this, target)
@ -64,49 +69,53 @@ trait SpawnPoint {
} }
object SpawnPoint { object SpawnPoint {
def Default(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (obj.Position, obj.Orientation) def Default(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = (obj.Position, obj.Orientation)
def Tube(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = ( def Tube(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) =
(
obj.Position + Vector3.z(1.5f), obj.Position + Vector3.z(1.5f),
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360) obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
) )
def AMS(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = { def AMS(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
//position the player alongside either of the AMS's terminals, facing away from it //position the player alongside either of the AMS's terminals, facing away from it
val ori = obj.Orientation val ori = obj.Orientation
val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left val side = if (System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
val x = ori.x val x = ori.x
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
val z = ori.z val z = ori.z
val zrot = (z + 90) % 360 val zrot = (z + 90) % 360
val zrad = math.toRadians(zrot) val zrad = math.toRadians(zrot)
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North val shift = Vector3(
math.sin(zrad).toFloat,
math.cos(zrad).toFloat,
0
) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
( (
obj.Position + shift + (if(x >= 330) { //ams leaning to the left obj.Position + shift + (if (x >= 330) { //ams leaning to the left
Vector3.z(xsin) Vector3.z(xsin)
} } else { //ams leaning to the right
else { //ams leaning to the right
Vector3.z(-xsin) Vector3.z(-xsin)
}), }),
if(side == 1) { if (side == 1) {
Vector3.z(zrot) Vector3.z(zrot)
} } else {
else {
Vector3.z((z - 90) % 360) Vector3.z((z - 90) % 360)
} }
) )
} }
def Gate(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = { def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
obj.Definition match { obj.Definition match {
case d : SpawnPointDefinition => case d: SpawnPointDefinition =>
val ori = target.Orientation val ori = target.Orientation
val zrad = math.toRadians(ori.z) val zrad = math.toRadians(ori.z)
val radius = scala.math.random.toFloat * d.UseRadius/2 + 20f //20 is definitely outside of the gating energy field val radius =
scala.math.random.toFloat * d.UseRadius / 2 + 20f //20 is definitely outside of the gating energy field
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
val altitudeShift = target.Definition match { val altitudeShift = target.Definition match {
case vdef : VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) => case vdef: VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
Vector3.z(scala.math.random.toFloat * d.UseRadius/4 + 20f) Vector3.z(scala.math.random.toFloat * d.UseRadius / 4 + 20f)
case _ => case _ =>
Vector3.Zero Vector3.Zero
} }
@ -118,46 +127,45 @@ object SpawnPoint {
} }
trait SpawnPointDefinition { trait SpawnPointDefinition {
private var radius : Float = 0f //m private var radius: Float = 0f //m
private var delay : Long = 0 //s private var delay: Long = 0 //s
private var noWarp : Option[mutable.Set[VehicleDefinition]] = None private var noWarp: Option[mutable.Set[VehicleDefinition]] = None
private var spawningFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default private var spawningFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
def UseRadius : Float = radius def UseRadius: Float = radius
def UseRadius_=(rad : Float) : Float = { def UseRadius_=(rad: Float): Float = {
radius = rad radius = rad
UseRadius UseRadius
} }
def Delay : Long = delay def Delay: Long = delay
def Delay_=(toDelay : Long) : Long = { def Delay_=(toDelay: Long): Long = {
delay = toDelay delay = toDelay
Delay Delay
} }
def VehicleAllowance : Boolean = noWarp.isDefined def VehicleAllowance: Boolean = noWarp.isDefined
def VehicleAllowance_=(allow : Boolean) : Boolean = { def VehicleAllowance_=(allow: Boolean): Boolean = {
if(allow && noWarp.isEmpty) { if (allow && noWarp.isEmpty) {
noWarp = Some(mutable.Set.empty[VehicleDefinition]) noWarp = Some(mutable.Set.empty[VehicleDefinition])
} } else if (!allow && noWarp.isDefined) {
else if(!allow && noWarp.isDefined) {
noWarp = None noWarp = None
} }
VehicleAllowance VehicleAllowance
} }
def NoWarp : mutable.Set[VehicleDefinition] = { def NoWarp: mutable.Set[VehicleDefinition] = {
noWarp.getOrElse(mutable.Set.empty[VehicleDefinition]) noWarp.getOrElse(mutable.Set.empty[VehicleDefinition])
} }
def SpecificPointFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc def SpecificPointFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
def SpecificPointFunc_=(func : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)) : Unit = { def SpecificPointFunc_=(func: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)): Unit = {
spawningFunc = func spawningFunc = func
} }
def SpecificPoint(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = spawningFunc(obj, target) def SpecificPoint(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = spawningFunc(obj, target)
} }

View file

@ -4,11 +4,10 @@ package net.psforever.objects
import net.psforever.objects.ce.TelepadLike import net.psforever.objects.ce.TelepadLike
import net.psforever.objects.definition.ConstructionItemDefinition import net.psforever.objects.definition.ConstructionItemDefinition
class Telepad(private val cdef : ConstructionItemDefinition) extends ConstructionItem(cdef) class Telepad(private val cdef: ConstructionItemDefinition) extends ConstructionItem(cdef) with TelepadLike
with TelepadLike
object Telepad { object Telepad {
def apply(cdef : ConstructionItemDefinition) : Telepad = { def apply(cdef: ConstructionItemDefinition): Telepad = {
new Telepad(cdef) new Telepad(cdef)
} }
} }

View file

@ -4,5 +4,4 @@ package net.psforever.objects
import net.psforever.objects.ce.{SimpleDeployable, TelepadLike} import net.psforever.objects.ce.{SimpleDeployable, TelepadLike}
import net.psforever.objects.definition.SimpleDeployableDefinition import net.psforever.objects.definition.SimpleDeployableDefinition
class TelepadDeployable(ddef : SimpleDeployableDefinition) extends SimpleDeployable(ddef) class TelepadDeployable(ddef: SimpleDeployableDefinition) extends SimpleDeployable(ddef) with TelepadLike
with TelepadLike

View file

@ -17,77 +17,79 @@ import scala.annotation.tailrec
* Some weapons Chainblade have ammunition but do not consume it. * Some weapons Chainblade have ammunition but do not consume it.
* @param toolDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields * @param toolDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/ */
class Tool(private val toolDef : ToolDefinition) extends Equipment class Tool(private val toolDef: ToolDefinition)
extends Equipment
with FireModeSwitch[FireModeDefinition] with FireModeSwitch[FireModeDefinition]
with JammableUnit { with JammableUnit {
/** index of the current fire mode on the `ToolDefinition`'s list of fire modes */ /** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
private var fireModeIndex : Int = toolDef.DefaultFireModeIndex private var fireModeIndex: Int = toolDef.DefaultFireModeIndex
/** current ammunition slot being used by this fire mode */ /** current ammunition slot being used by this fire mode */
private var ammoSlots : List[Tool.FireModeSlot] = List.empty private var ammoSlots: List[Tool.FireModeSlot] = List.empty
var lastDischarge : Long = 0 var lastDischarge: Long = 0
Tool.LoadDefinition(this) Tool.LoadDefinition(this)
def FireModeIndex : Int = fireModeIndex def FireModeIndex: Int = fireModeIndex
def FireModeIndex_=(index : Int) : Int = { def FireModeIndex_=(index: Int): Int = {
fireModeIndex = index % Definition.FireModes.length fireModeIndex = index % Definition.FireModes.length
FireModeIndex FireModeIndex
} }
def FireMode : FireModeDefinition = Definition.FireModes(fireModeIndex) def FireMode: FireModeDefinition = Definition.FireModes(fireModeIndex)
def NextFireMode : FireModeDefinition = { def NextFireMode: FireModeDefinition = {
FireModeIndex = Definition.NextFireModeIndex(FireModeIndex) FireModeIndex = Definition.NextFireModeIndex(FireModeIndex)
AmmoSlot.Chamber = FireMode.Chamber AmmoSlot.Chamber = FireMode.Chamber
FireMode FireMode
} }
def ToFireMode : Int = Definition.NextFireModeIndex(FireModeIndex) def ToFireMode: Int = Definition.NextFireModeIndex(FireModeIndex)
def ToFireMode_=(index : Int) : FireModeDefinition = { def ToFireMode_=(index: Int): FireModeDefinition = {
FireModeIndex = index FireModeIndex = index
AmmoSlot.Chamber = FireMode.Chamber AmmoSlot.Chamber = FireMode.Chamber
FireMode FireMode
} }
def AmmoTypeIndex : Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex) def AmmoTypeIndex: Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
def AmmoTypeIndex_=(index : Int) : Int = { def AmmoTypeIndex_=(index: Int): Int = {
AmmoSlot.AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length AmmoSlot.AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length
AmmoTypeIndex AmmoTypeIndex
} }
def AmmoType : Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType def AmmoType: Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType
def NextAmmoType : Ammo.Value = { def NextAmmoType: Ammo.Value = {
AmmoSlot.AmmoTypeIndex = AmmoSlot.AmmoTypeIndex + 1 AmmoSlot.AmmoTypeIndex = AmmoSlot.AmmoTypeIndex + 1
AmmoType AmmoType
} }
def Projectile : ProjectileDefinition = { def Projectile: ProjectileDefinition = {
Definition.ProjectileTypes({ Definition.ProjectileTypes({
val projIndices = FireMode.ProjectileTypeIndices val projIndices = FireMode.ProjectileTypeIndices
if(projIndices.isEmpty) { if (projIndices.isEmpty) {
AmmoTypeIndex //e.g., bullet_9mm -> bullet_9mm_projectile, bullet_9mm_AP -> bullet_9mm_AP_projectile AmmoTypeIndex //e.g., bullet_9mm -> bullet_9mm_projectile, bullet_9mm_AP -> bullet_9mm_AP_projectile
} } else {
else {
projIndices(AmmoSlot.AmmoTypeIndex) //e.g., pulsar: f.mode1 -> pulsar_projectile, f.mode2 = pulsar_ap_projectile projIndices(AmmoSlot.AmmoTypeIndex) //e.g., pulsar: f.mode1 -> pulsar_projectile, f.mode2 = pulsar_ap_projectile
} }
}) })
} }
def ProjectileType : Projectiles.Value = Projectile.ProjectileType def ProjectileType: Projectiles.Value = Projectile.ProjectileType
def Magazine : Int = AmmoSlot.Magazine def Magazine: Int = AmmoSlot.Magazine
def Magazine_=(mag : Int) : Int = { def Magazine_=(mag: Int): Int = {
//AmmoSlot.Magazine = Math.min(Math.max(0, mag), MaxMagazine) //AmmoSlot.Magazine = Math.min(Math.max(0, mag), MaxMagazine)
AmmoSlot.Magazine = Math.max(0, mag) AmmoSlot.Magazine = Math.max(0, mag)
Magazine Magazine
} }
def MaxMagazine : Int = { def MaxMagazine: Int = {
val fmode = FireMode val fmode = FireMode
fmode.CustomMagazine.get(AmmoType) match { fmode.CustomMagazine.get(AmmoType) match {
case Some(magSize) => case Some(magSize) =>
@ -97,30 +99,30 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment
} }
} }
def Discharge(rounds : Option[Int] = None) : Int = { def Discharge(rounds: Option[Int] = None): Int = {
lastDischarge = System.nanoTime() lastDischarge = System.nanoTime()
Magazine = FireMode.Discharge(this, rounds) Magazine = FireMode.Discharge(this, rounds)
} }
def LastDischarge : Long = { def LastDischarge: Long = {
lastDischarge lastDischarge
} }
def AmmoSlot : Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex) def AmmoSlot: Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
def AmmoSlots : List[Tool.FireModeSlot] = ammoSlots def AmmoSlots: List[Tool.FireModeSlot] = ammoSlots
def MaxAmmoSlot : Int = ammoSlots.length def MaxAmmoSlot: Int = ammoSlots.length
def Definition : ToolDefinition = toolDef def Definition: ToolDefinition = toolDef
override def toString : String = Tool.toString(this) override def toString: String = Tool.toString(this)
} }
//AmmoType = Definition.AmmoTypes( (Definition.FireModes(fireModeIndex)).AmmoTypeIndices( (ammoSlots((Definition.FireModes(fireModeIndex)).AmmoSlotIndex)).AmmoTypeIndex) ).AmmoType //AmmoType = Definition.AmmoTypes( (Definition.FireModes(fireModeIndex)).AmmoTypeIndices( (ammoSlots((Definition.FireModes(fireModeIndex)).AmmoSlotIndex)).AmmoTypeIndex) ).AmmoType
object Tool { object Tool {
def apply(toolDef : ToolDefinition) : Tool = { def apply(toolDef: ToolDefinition): Tool = {
new Tool(toolDef) new Tool(toolDef)
} }
@ -128,28 +130,34 @@ object Tool {
* Use the `*Definition` that was provided to this object to initialize its fields and settings. * Use the `*Definition` that was provided to this object to initialize its fields and settings.
* @param tool the `Tool` being initialized * @param tool the `Tool` being initialized
*/ */
def LoadDefinition(tool : Tool) : Unit = { def LoadDefinition(tool: Tool): Unit = {
val tdef : ToolDefinition = tool.Definition val tdef: ToolDefinition = tool.Definition
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
tool.ammoSlots = buildFireModes(tdef, (0 to maxSlot).iterator, tdef.FireModes.toList) tool.ammoSlots = buildFireModes(tdef, (0 to maxSlot).iterator, tdef.FireModes.toList)
} }
@tailrec private def buildFireModes(tdef : ToolDefinition, iter : Iterator[Int], fmodes : List[FireModeDefinition], list : List[FireModeSlot] = Nil) : List[FireModeSlot] = { @tailrec private def buildFireModes(
if(!iter.hasNext) { tdef: ToolDefinition,
iter: Iterator[Int],
fmodes: List[FireModeDefinition],
list: List[FireModeSlot] = Nil
): List[FireModeSlot] = {
if (!iter.hasNext) {
list list
} } else {
else {
val index = iter.next val index = iter.next
fmodes.filter(fmode => fmode.AmmoSlotIndex == index) match { fmodes.filter(fmode => fmode.AmmoSlotIndex == index) match {
case fmode :: _ => case fmode :: _ =>
buildFireModes(tdef, iter, fmodes, list :+ new FireModeSlot(tdef, fmode)) buildFireModes(tdef, iter, fmodes, list :+ new FireModeSlot(tdef, fmode))
case Nil => case Nil =>
throw new IllegalArgumentException(s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip") throw new IllegalArgumentException(
s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip"
)
} }
} }
} }
def toString(obj : Tool) : String = { def toString(obj: Tool): String = {
s"${obj.Definition.Name} (mode=${obj.FireModeIndex}-${obj.AmmoType})(${obj.Magazine}/${obj.MaxMagazine})" s"${obj.Definition.Name} (mode=${obj.FireModeIndex}-${obj.AmmoType})(${obj.Magazine}/${obj.MaxMagazine})"
} }
@ -166,24 +174,26 @@ object Tool {
* two exclusive groups of ammunition divided into 2 cycled types and 4 cycled types - * two exclusive groups of ammunition divided into 2 cycled types and 4 cycled types -
* is an example of a weapon that benefits from this implementation. * is an example of a weapon that benefits from this implementation.
*/ */
class FireModeSlot(private val tdef : ToolDefinition, private val fdef : FireModeDefinition) { class FireModeSlot(private val tdef: ToolDefinition, private val fdef: FireModeDefinition) {
/** /**
* if this fire mode has multiple types of ammunition * if this fire mode has multiple types of ammunition
* this is the index of the fire mode's ammo List, not a reference to the tool's ammo List * this is the index of the fire mode's ammo List, not a reference to the tool's ammo List
*/ */
private var ammoTypeIndex : Int = 0 private var ammoTypeIndex: Int = 0
/** a reference to the actual `AmmoBox` of this slot */ /** a reference to the actual `AmmoBox` of this slot */
private var box : AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine) private var box: AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine)
private var chamber = fdef.Chamber private var chamber = fdef.Chamber
def AmmoTypeIndex : Int = ammoTypeIndex def AmmoTypeIndex: Int = ammoTypeIndex
def AmmoTypeIndex_=(index : Int) : Int = { def AmmoTypeIndex_=(index: Int): Int = {
ammoTypeIndex = index % fdef.AmmoTypeIndices.length ammoTypeIndex = index % fdef.AmmoTypeIndices.length
AmmoTypeIndex AmmoTypeIndex
} }
private def AmmoDefinition : AmmoBoxDefinition = { private def AmmoDefinition: AmmoBoxDefinition = {
tdef.AmmoTypes(fdef.AmmoTypeIndices(ammoTypeIndex)) tdef.AmmoTypes(fdef.AmmoTypeIndices(ammoTypeIndex))
} }
@ -193,40 +203,39 @@ object Tool {
* Generally, convert from this index, to the index in the fire mode's ammunition list, to the index in the `ToolDefinition`'s ammunition list. * Generally, convert from this index, to the index in the fire mode's ammunition list, to the index in the `ToolDefinition`'s ammunition list.
* @return the `Ammo` type that should be loaded into the magazine right now * @return the `Ammo` type that should be loaded into the magazine right now
*/ */
def AmmoType : Ammo.Value = AmmoDefinition.AmmoType def AmmoType: Ammo.Value = AmmoDefinition.AmmoType
def AllAmmoTypes : List[Ammo.Value] = { def AllAmmoTypes: List[Ammo.Value] = {
fdef.AmmoTypeIndices.map(index => tdef.AmmoTypes(fdef.AmmoTypeIndices(index)).AmmoType).toList fdef.AmmoTypeIndices.map(index => tdef.AmmoTypes(fdef.AmmoTypeIndices(index)).AmmoType).toList
} }
def Magazine : Int = box.Capacity def Magazine: Int = box.Capacity
def Magazine_=(mag : Int) : Int = { def Magazine_=(mag: Int): Int = {
box.Capacity = mag box.Capacity = mag
Magazine Magazine
} }
def Chamber : Int = chamber def Chamber: Int = chamber
def Chamber_=(chmbr : Int) : Int = { def Chamber_=(chmbr: Int): Int = {
chamber = math.min(math.max(0, chmbr), fdef.Chamber) chamber = math.min(math.max(0, chmbr), fdef.Chamber)
Chamber Chamber
} }
def Box : AmmoBox = box def Box: AmmoBox = box
def Box_=(toBox : AmmoBox) : Option[AmmoBox] = { def Box_=(toBox: AmmoBox): Option[AmmoBox] = {
if(toBox.AmmoType == AmmoType) { if (toBox.AmmoType == AmmoType) {
box = toBox box = toBox
Some(Box) Some(Box)
} } else {
else {
None None
} }
} }
def Tool : ToolDefinition = tdef def Tool: ToolDefinition = tdef
def Definition : FireModeDefinition = fdef def Definition: FireModeDefinition = fdef
} }
} }

View file

@ -11,40 +11,39 @@ import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
import net.psforever.objects.serverobject.repair.RepairableEntity import net.psforever.objects.serverobject.repair.RepairableEntity
import net.psforever.objects.vital.StandardResolutions import net.psforever.objects.vital.StandardResolutions
class TrapDeployable(cdef : TrapDeployableDefinition) extends ComplexDeployable(cdef) class TrapDeployable(cdef: TrapDeployableDefinition) extends ComplexDeployable(cdef)
class TrapDeployableDefinition(objectId : Int) extends ComplexDeployableDefinition(objectId) { class TrapDeployableDefinition(objectId: Int) extends ComplexDeployableDefinition(objectId) {
Model = StandardResolutions.SimpleDeployables Model = StandardResolutions.SimpleDeployables
Packet = new TRAPConverter Packet = new TRAPConverter
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[TrapDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor = context.actorOf(Props(classOf[TrapDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context) SimpleDeployableDefinition.SimpleUninitialize(obj, context)
} }
} }
object TrapDeployableDefinition { object TrapDeployableDefinition {
def apply(dtype : DeployedItem.Value) : TrapDeployableDefinition = { def apply(dtype: DeployedItem.Value): TrapDeployableDefinition = {
new TrapDeployableDefinition(dtype.id) new TrapDeployableDefinition(dtype.id)
} }
} }
class TrapDeployableControl(trap : TrapDeployable) extends Actor class TrapDeployableControl(trap: TrapDeployable) extends Actor with DamageableEntity with RepairableEntity {
with DamageableEntity
with RepairableEntity {
def DamageableObject = trap def DamageableObject = trap
def RepairableObject = trap def RepairableObject = trap
def receive : Receive = takesDamage def receive: Receive =
takesDamage
.orElse(canBeRepairedByNanoDispenser) .orElse(canBeRepairedByNanoDispenser)
.orElse { .orElse {
case _ => case _ =>
} }
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = { override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause) super.DestructionAwareness(target, cause)
Deployables.AnnounceDestroyDeployable(trap, None) Deployables.AnnounceDestroyDeployable(trap, None)
} }

View file

@ -17,18 +17,20 @@ import net.psforever.objects.serverobject.repair.RepairableWeaponTurret
import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret} import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret}
import net.psforever.objects.vital.{StandardResolutions, StandardVehicleDamage, StandardVehicleResistance} import net.psforever.objects.vital.{StandardResolutions, StandardVehicleDamage, StandardVehicleResistance}
class TurretDeployable(tdef : TurretDeployableDefinition) extends ComplexDeployable(tdef) class TurretDeployable(tdef: TurretDeployableDefinition)
extends ComplexDeployable(tdef)
with WeaponTurret with WeaponTurret
with JammableUnit with JammableUnit
with Hackable { with Hackable {
WeaponTurret.LoadDefinition(this) WeaponTurret.LoadDefinition(this)
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
override def Definition = tdef override def Definition = tdef
} }
class TurretDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) class TurretDeployableDefinition(private val objectId: Int)
extends ComplexDeployableDefinition(objectId)
with TurretDefinition { with TurretDefinition {
Name = "turret_deployable" Name = "turret_deployable"
Packet = new SmallTurretConverter Packet = new SmallTurretConverter
@ -37,28 +39,29 @@ class TurretDeployableDefinition(private val objectId : Int) extends ComplexDepl
Model = StandardResolutions.FacilityTurrets Model = StandardResolutions.FacilityTurrets
//override to clarify inheritance conflict //override to clarify inheritance conflict
override def MaxHealth : Int = super[ComplexDeployableDefinition].MaxHealth override def MaxHealth: Int = super[ComplexDeployableDefinition].MaxHealth
//override to clarify inheritance conflict //override to clarify inheritance conflict
override def MaxHealth_=(max : Int) : Int = super[ComplexDeployableDefinition].MaxHealth_=(max) override def MaxHealth_=(max: Int): Int = super[ComplexDeployableDefinition].MaxHealth_=(max)
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[TurretControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor = context.actorOf(Props(classOf[TurretControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context) SimpleDeployableDefinition.SimpleUninitialize(obj, context)
} }
} }
object TurretDeployableDefinition { object TurretDeployableDefinition {
def apply(dtype : DeployedItem.Value) : TurretDeployableDefinition = { def apply(dtype: DeployedItem.Value): TurretDeployableDefinition = {
new TurretDeployableDefinition(dtype.id) new TurretDeployableDefinition(dtype.id)
} }
} }
/** control actors */ /** control actors */
class TurretControl(turret : TurretDeployable) extends Actor class TurretControl(turret: TurretDeployable)
extends Actor
with FactionAffinityBehavior.Check with FactionAffinityBehavior.Check
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
with MountableBehavior.TurretMount with MountableBehavior.TurretMount
@ -71,7 +74,8 @@ class TurretControl(turret : TurretDeployable) extends Actor
def DamageableObject = turret def DamageableObject = turret
def RepairableObject = turret def RepairableObject = turret
def receive : Receive = checkBehavior def receive: Receive =
checkBehavior
.orElse(jammableBehavior) .orElse(jammableBehavior)
.orElse(mountBehavior) .orElse(mountBehavior)
.orElse(dismountBehavior) .orElse(dismountBehavior)
@ -81,7 +85,7 @@ class TurretControl(turret : TurretDeployable) extends Actor
case _ => ; case _ => ;
} }
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = { override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause) super.DestructionAwareness(target, cause)
Deployables.AnnounceDestroyDeployable(turret, None) Deployables.AnnounceDestroyDeployable(turret, None)
} }

View file

@ -66,7 +66,8 @@ import scala.util.{Success, Try}
* stores and unloads pertinent information about the `Vehicle`'s configuration; * stores and unloads pertinent information about the `Vehicle`'s configuration;
* used in the initialization process (`loadVehicleDefinition`) * used in the initialization process (`loadVehicleDefinition`)
*/ */
class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner class Vehicle(private val vehicleDef: VehicleDefinition)
extends AmenityOwner
with Hackable with Hackable
with FactionAffinity with FactionAffinity
with Mountable with Mountable
@ -77,34 +78,36 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
with StandardResistanceProfile with StandardResistanceProfile
with JammableUnit with JammableUnit
with Container { with Container {
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private var shields : Int = 0 private var shields: Int = 0
private var decal : Int = 0 private var decal: Int = 0
private var trunkAccess : Option[PlanetSideGUID] = None private var trunkAccess: Option[PlanetSideGUID] = None
private var jammered : Boolean = false private var jammered: Boolean = false
private var cloaked : Boolean = false private var cloaked: Boolean = false
private var flying : Boolean = false private var flying: Boolean = false
private var ntuCapacitor : Int = 0 private var ntuCapacitor: Int = 0
private var capacitor : Int = 0 private var capacitor: Int = 0
/** /**
* Permissions control who gets to access different parts of the vehicle; * Permissions control who gets to access different parts of the vehicle;
* the groups are Driver (seat), Gunner (seats), Passenger (seats), and the Trunk * the groups are Driver (seat), Gunner (seats), Passenger (seats), and the Trunk
*/ */
private val groupPermissions : Array[VehicleLockState.Value] = Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked) private val groupPermissions: Array[VehicleLockState.Value] =
private var seats : Map[Int, Seat] = Map.empty Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
private var cargoHolds : Map[Int, Cargo] = Map.empty private var seats: Map[Int, Seat] = Map.empty
private var weapons : Map[Int, EquipmentSlot] = Map.empty private var cargoHolds: Map[Int, Cargo] = Map.empty
private var utilities : Map[Int, Utility] = Map() private var weapons: Map[Int, EquipmentSlot] = Map.empty
private val trunk : GridInventory = GridInventory() private var utilities: Map[Int, Utility] = Map()
private val trunk: GridInventory = GridInventory()
/** /**
* Records the GUID of the cargo vehicle (galaxy/lodestar) this vehicle is stored in for DismountVehicleCargoMsg use * Records the GUID of the cargo vehicle (galaxy/lodestar) this vehicle is stored in for DismountVehicleCargoMsg use
* DismountVehicleCargoMsg only passes the player_guid and this vehicle's guid * DismountVehicleCargoMsg only passes the player_guid and this vehicle's guid
*/ */
private var mountedIn : Option[PlanetSideGUID] = None private var mountedIn: Option[PlanetSideGUID] = None
private var vehicleGatingManifest : Option[VehicleManifest] = None private var vehicleGatingManifest: Option[VehicleManifest] = None
private var previousVehicleGatingManifest : Option[VehicleManifest] = None private var previousVehicleGatingManifest: Option[VehicleManifest] = None
//init //init
LoadDefinition() LoadDefinition()
@ -113,15 +116,15 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* Override this method to perform any special setup that is not standardized to `*Definition`. * Override this method to perform any special setup that is not standardized to `*Definition`.
* @see `Vehicle.LoadDefinition` * @see `Vehicle.LoadDefinition`
*/ */
protected def LoadDefinition() : Unit = { protected def LoadDefinition(): Unit = {
Vehicle.LoadDefinition(this) Vehicle.LoadDefinition(this)
} }
def Faction : PlanetSideEmpire.Value = { def Faction: PlanetSideEmpire.Value = {
this.faction this.faction
} }
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = { override def Faction_=(faction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
this.faction = faction this.faction = faction
faction faction
} }
@ -129,13 +132,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
/** How long it takes to jack the vehicle in seconds, based on the hacker's certification level */ /** How long it takes to jack the vehicle in seconds, based on the hacker's certification level */
def JackingDuration: Array[Int] = Definition.JackingDuration def JackingDuration: Array[Int] = Definition.JackingDuration
def MountedIn : Option[PlanetSideGUID] = { def MountedIn: Option[PlanetSideGUID] = {
this.mountedIn this.mountedIn
} }
def MountedIn_=(cargo_vehicle_guid : PlanetSideGUID) : Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid)) def MountedIn_=(cargo_vehicle_guid: PlanetSideGUID): Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
def MountedIn_=(cargo_vehicle_guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def MountedIn_=(cargo_vehicle_guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
cargo_vehicle_guid match { cargo_vehicle_guid match {
case Some(_) => case Some(_) =>
this.mountedIn = cargo_vehicle_guid this.mountedIn = cargo_vehicle_guid
@ -145,61 +148,61 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
MountedIn MountedIn
} }
override def Health_=(assignHealth : Int) : Int = { override def Health_=(assignHealth: Int): Int = {
//TODO should vehicle class enforce this? //TODO should vehicle class enforce this?
if(!Destroyed) { if (!Destroyed) {
super.Health_=(assignHealth) super.Health_=(assignHealth)
} }
Health Health
} }
def Shields : Int = { def Shields: Int = {
shields shields
} }
def Shields_=(strength : Int) : Int = { def Shields_=(strength: Int): Int = {
shields = math.min(math.max(0, strength), MaxShields) shields = math.min(math.max(0, strength), MaxShields)
Shields Shields
} }
def MaxShields : Int = { def MaxShields: Int = {
Definition.MaxShields Definition.MaxShields
} }
def Decal : Int = { def Decal: Int = {
decal decal
} }
def Decal_=(logo : Int) : Int = { def Decal_=(logo: Int): Int = {
decal = logo decal = logo
Decal Decal
} }
def Jammered : Boolean = jammered def Jammered: Boolean = jammered
def Jammered_=(jamState : Boolean) : Boolean = { def Jammered_=(jamState: Boolean): Boolean = {
jammered = jamState jammered = jamState
Jammered Jammered
} }
def Cloaked : Boolean = cloaked def Cloaked: Boolean = cloaked
def Cloaked_=(isCloaked : Boolean) : Boolean = { def Cloaked_=(isCloaked: Boolean): Boolean = {
cloaked = isCloaked cloaked = isCloaked
Cloaked Cloaked
} }
def Flying : Boolean = flying def Flying: Boolean = flying
def Flying_=(isFlying : Boolean) : Boolean = { def Flying_=(isFlying: Boolean): Boolean = {
flying = isFlying flying = isFlying
Flying Flying
} }
def NtuCapacitor : Int = ntuCapacitor def NtuCapacitor: Int = ntuCapacitor
def NtuCapacitor_=(value: Int) : Int = { def NtuCapacitor_=(value: Int): Int = {
if(value > Definition.MaxNtuCapacitor) { if (value > Definition.MaxNtuCapacitor) {
ntuCapacitor = Definition.MaxNtuCapacitor ntuCapacitor = Definition.MaxNtuCapacitor
} else if (value < 0) { } else if (value < 0) {
ntuCapacitor = 0 ntuCapacitor = 0
@ -219,8 +222,8 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
def Capacitor : Int = capacitor def Capacitor : Int = capacitor
def Capacitor_=(value: Int) : Int = { def Capacitor_=(value: Int): Int = {
if(value > Definition.MaxCapacitor) { if (value > Definition.MaxCapacitor) {
capacitor = Definition.MaxCapacitor capacitor = Definition.MaxCapacitor
} else if (value < 0) { } else if (value < 0) {
capacitor = 0 capacitor = 0
@ -235,18 +238,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param mountPoint an index representing the seat position / mounting point * @param mountPoint an index representing the seat position / mounting point
* @return a seat number, or `None` * @return a seat number, or `None`
*/ */
def GetSeatFromMountPoint(mountPoint : Int) : Option[Int] = { def GetSeatFromMountPoint(mountPoint: Int): Option[Int] = {
Definition.MountPoints.get(mountPoint) Definition.MountPoints.get(mountPoint)
} }
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
/** /**
* What are the access permissions for a position on this vehicle, seats or trunk? * What are the access permissions for a position on this vehicle, seats or trunk?
* @param group the group index * @param group the group index
* @return what sort of access permission exist for this group * @return what sort of access permission exist for this group
*/ */
def PermissionGroup(group : Int) : Option[VehicleLockState.Value] = { def PermissionGroup(group: Int): Option[VehicleLockState.Value] = {
reindexPermissionsGroup(group) match { reindexPermissionsGroup(group) match {
case Some(index) => case Some(index) =>
Some(groupPermissions(index)) Some(groupPermissions(index))
@ -262,16 +265,17 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @return the new access permission for this group; * @return the new access permission for this group;
* `None`, if the group does not exist or the level of permission was not changed * `None`, if the group does not exist or the level of permission was not changed
*/ */
def PermissionGroup(group : Int, level : Long) : Option[VehicleLockState.Value] = { def PermissionGroup(group: Int, level: Long): Option[VehicleLockState.Value] = {
reindexPermissionsGroup(group) match { reindexPermissionsGroup(group) match {
case Some(index) => case Some(index) =>
val current = groupPermissions(index) val current = groupPermissions(index)
val next = try { VehicleLockState(level.toInt) } catch { case _ : Exception => groupPermissions(index) } val next =
if(current != next) { try { VehicleLockState(level.toInt) }
catch { case _: Exception => groupPermissions(index) }
if (current != next) {
groupPermissions(index) = next groupPermissions(index) = next
PermissionGroup(index) PermissionGroup(index)
} } else {
else {
None None
} }
case None => case None =>
@ -285,13 +289,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param group the group index * @param group the group index
* @return the modified group index * @return the modified group index
*/ */
private def reindexPermissionsGroup(group : Int) : Option[Int] = if(group > 9 && group < 14) { private def reindexPermissionsGroup(group: Int): Option[Int] =
if (group > 9 && group < 14) {
Some(group - 10) Some(group - 10)
} } else if (group > -1 && group < 4) {
else if(group > -1 && group < 4) {
Some(group) Some(group)
} } else {
else {
None None
} }
@ -301,37 +304,34 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param seatNumber an index representing the seat position / mounting point * @param seatNumber an index representing the seat position / mounting point
* @return a `Seat`, or `None` * @return a `Seat`, or `None`
*/ */
def Seat(seatNumber : Int) : Option[Seat] = { def Seat(seatNumber: Int): Option[Seat] = {
if(seatNumber >= 0 && seatNumber < this.seats.size) { if (seatNumber >= 0 && seatNumber < this.seats.size) {
this.seats.get(seatNumber) this.seats.get(seatNumber)
} } else {
else {
None None
} }
} }
def Seats : Map[Int, Seat] = { def Seats: Map[Int, Seat] = {
seats seats
} }
def CargoHold(cargoNumber : Int) : Option[Cargo] = { def CargoHold(cargoNumber: Int): Option[Cargo] = {
if(cargoNumber >= 0) { if (cargoNumber >= 0) {
this.cargoHolds.get(cargoNumber) this.cargoHolds.get(cargoNumber)
} } else {
else {
None None
} }
} }
def CargoHolds : Map[Int, Cargo] = { def CargoHolds: Map[Int, Cargo] = {
cargoHolds cargoHolds
} }
def SeatPermissionGroup(seatNumber : Int) : Option[AccessPermissionGroup.Value] = { def SeatPermissionGroup(seatNumber: Int): Option[AccessPermissionGroup.Value] = {
if(seatNumber == 0) { if (seatNumber == 0) {
Some(AccessPermissionGroup.Driver) Some(AccessPermissionGroup.Driver)
} } else {
else {
Seat(seatNumber) match { Seat(seatNumber) match {
case Some(seat) => case Some(seat) =>
seat.ControlledWeapon match { seat.ControlledWeapon match {
@ -351,14 +351,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
} }
} }
def Weapons : Map[Int, EquipmentSlot] = weapons def Weapons: Map[Int, EquipmentSlot] = weapons
/** /**
* Get the weapon at the index. * Get the weapon at the index.
* @param wepNumber an index representing the seat position / mounting point * @param wepNumber an index representing the seat position / mounting point
* @return a weapon, or `None` * @return a weapon, or `None`
*/ */
def ControlledWeapon(wepNumber : Int) : Option[Equipment] = { def ControlledWeapon(wepNumber: Int): Option[Equipment] = {
weapons.get(wepNumber) match { weapons.get(wepNumber) match {
case Some(mount) => case Some(mount) =>
mount.Equipment mount.Equipment
@ -372,45 +372,42 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param player the player * @param player the player
* @return a seat number, or `None` if the `player` is not actually seated in this vehicle * @return a seat number, or `None` if the `player` is not actually seated in this vehicle
*/ */
def PassengerInSeat(player : Player) : Option[Int] = recursivePassengerInSeat(seats.iterator, player) def PassengerInSeat(player: Player): Option[Int] = recursivePassengerInSeat(seats.iterator, player)
@tailrec private def recursivePassengerInSeat(iter : Iterator[(Int, Seat)], player : Player) : Option[Int] = { @tailrec private def recursivePassengerInSeat(iter: Iterator[(Int, Seat)], player: Player): Option[Int] = {
if(!iter.hasNext) { if (!iter.hasNext) {
None None
} } else {
else {
val (seatNumber, seat) = iter.next val (seatNumber, seat) = iter.next
if(seat.Occupant.contains(player)) { if (seat.Occupant.contains(player)) {
Some(seatNumber) Some(seatNumber)
} } else {
else {
recursivePassengerInSeat(iter, player) recursivePassengerInSeat(iter, player)
} }
} }
} }
def Utilities : Map[Int, Utility] = utilities def Utilities: Map[Int, Utility] = utilities
/** /**
* Get a reference to a certain `Utility` attached to this `Vehicle`. * Get a reference to a certain `Utility` attached to this `Vehicle`.
* @param utilNumber the attachment number of the `Utility` * @param utilNumber the attachment number of the `Utility`
* @return the `Utility` or `None` (if invalid) * @return the `Utility` or `None` (if invalid)
*/ */
def Utility(utilNumber : Int) : Option[PlanetSideServerObject] = { def Utility(utilNumber: Int): Option[PlanetSideServerObject] = {
if(utilNumber >= 0 && utilNumber < this.utilities.size) { if (utilNumber >= 0 && utilNumber < this.utilities.size) {
this.utilities.get(utilNumber) match { this.utilities.get(utilNumber) match {
case Some(util) => case Some(util) =>
Some(util()) Some(util())
case None => case None =>
None None
} }
} } else {
else {
None None
} }
} }
def Utility(utilType : UtilityType.Value) : Option[PlanetSideServerObject] = { def Utility(utilType: UtilityType.Value): Option[PlanetSideServerObject] = {
utilities.values.find(_.UtilType == utilType) match { utilities.values.find(_.UtilType == utilType) match {
case Some(util) => case Some(util) =>
Some(util()) Some(util())
@ -423,30 +420,32 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
override def UndeployTime = Definition.UndeployTime override def UndeployTime = Definition.UndeployTime
def Inventory : GridInventory = trunk def Inventory: GridInventory = trunk
def VisibleSlots : Set[Int] = weapons.keySet def VisibleSlots: Set[Int] = weapons.keySet
override def Slot(slotNum : Int) : EquipmentSlot = { override def Slot(slotNum: Int): EquipmentSlot = {
weapons.get(slotNum) weapons
// .orElse(utilities.get(slotNum) match { .get(slotNum)
// case Some(_) => // .orElse(utilities.get(slotNum) match {
// //TODO what do now? // case Some(_) =>
// None // //TODO what do now?
// case None => ; // None
// None // case None => ;
// }) // None
.orElse(Some(Inventory.Slot(slotNum))).get // })
.orElse(Some(Inventory.Slot(slotNum)))
.get
} }
override def Find(guid : PlanetSideGUID) : Option[Int] = { override def Find(guid: PlanetSideGUID): Option[Int] = {
weapons.find({ case (_, obj) => weapons.find({
case (_, obj) =>
obj.Equipment match { obj.Equipment match {
case Some(item) => case Some(item) =>
if(item.HasGUID && item.GUID == guid) { if (item.HasGUID && item.GUID == guid) {
true true
} } else {
else {
false false
} }
case None => case None =>
@ -460,7 +459,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
} }
} }
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = { override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
weapons.get(dest) match { weapons.get(dest) match {
case Some(slot) => case Some(slot) =>
slot.Equipment match { slot.Equipment match {
@ -478,13 +477,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* A reference to the `Vehicle` `Trunk` space. * A reference to the `Vehicle` `Trunk` space.
* @return this `Vehicle` `Trunk` * @return this `Vehicle` `Trunk`
*/ */
def Trunk : GridInventory = { def Trunk: GridInventory = {
this.trunk this.trunk
} }
def AccessingTrunk : Option[PlanetSideGUID] = trunkAccess def AccessingTrunk: Option[PlanetSideGUID] = trunkAccess
def AccessingTrunk_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = { def AccessingTrunk_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
AccessingTrunk = Some(guid) AccessingTrunk = Some(guid)
} }
@ -494,12 +493,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param guid the player who wishes to access the trunk * @param guid the player who wishes to access the trunk
* @return the player who is currently allowed to access the trunk * @return the player who is currently allowed to access the trunk
*/ */
def AccessingTrunk_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def AccessingTrunk_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
guid match { guid match {
case None => case None =>
trunkAccess = None trunkAccess = None
case Some(player) => case Some(player) =>
if(trunkAccess.isEmpty) { if (trunkAccess.isEmpty) {
trunkAccess = Some(player) trunkAccess = Some(player)
} }
} }
@ -511,8 +510,8 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param player a player attempting to access this `Trunk` * @param player a player attempting to access this `Trunk`
* @return `true`, if the `player` is permitted access; `false`, otherwise * @return `true`, if the `player` is permitted access; `false`, otherwise
*/ */
def CanAccessTrunk(player : Player) : Boolean = { def CanAccessTrunk(player: Player): Boolean = {
if(trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) { if (trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
groupPermissions(3) match { groupPermissions(3) match {
case VehicleLockState.Locked => //only the owner case VehicleLockState.Locked => //only the owner
Owner.isEmpty || (Owner.isDefined && player.GUID == Owner.get) Owner.isEmpty || (Owner.isDefined && player.GUID == Owner.get)
@ -521,8 +520,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
case VehicleLockState.Empire => //anyone of the owner's faction case VehicleLockState.Empire => //anyone of the owner's faction
faction == player.Faction faction == player.Faction
} }
} } else {
else {
false false
} }
} }
@ -531,18 +529,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* Check access to the `Trunk`. * Check access to the `Trunk`.
* @return the current access value for the `Vehicle` `Trunk` * @return the current access value for the `Vehicle` `Trunk`
*/ */
def TrunkLockState : VehicleLockState.Value = groupPermissions(3) def TrunkLockState: VehicleLockState.Value = groupPermissions(3)
/** /**
* Trunk locations are stored as the orientation zero point being to the East. We need to convert that to a North = 0 orientation before returning the location * Trunk locations are stored as the orientation zero point being to the East. We need to convert that to a North = 0 orientation before returning the location
* @return A Vector3 of the current trunk location, orientated with North as the zero point * @return A Vector3 of the current trunk location, orientated with North as the zero point
*/ */
def TrunkLocation : Vector3 = { def TrunkLocation: Vector3 = {
val rotationRadians = -math.toRadians(Orientation.z - 90f).toFloat val rotationRadians = -math.toRadians(Orientation.z - 90f).toFloat
Vector3.PlanarRotateAroundPoint(Position + Definition.TrunkLocation, Position, rotationRadians) Vector3.PlanarRotateAroundPoint(Position + Definition.TrunkLocation, Position, rotationRadians)
} }
def PrepareGatingManifest() : VehicleManifest = { def PrepareGatingManifest(): VehicleManifest = {
val manifest = VehicleManifest(this) val manifest = VehicleManifest(this)
seats.collect { case (index, seat) if index > 0 => seat.Occupant = None } seats.collect { case (index, seat) if index > 0 => seat.Occupant = None }
vehicleGatingManifest = Some(manifest) vehicleGatingManifest = Some(manifest)
@ -550,14 +548,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
manifest manifest
} }
def PublishGatingManifest() : Option[VehicleManifest] = { def PublishGatingManifest(): Option[VehicleManifest] = {
val out = vehicleGatingManifest val out = vehicleGatingManifest
previousVehicleGatingManifest = vehicleGatingManifest previousVehicleGatingManifest = vehicleGatingManifest
vehicleGatingManifest = None vehicleGatingManifest = None
out out
} }
def PreviousGatingManifest() : Option[VehicleManifest] = previousVehicleGatingManifest def PreviousGatingManifest(): Option[VehicleManifest] = previousVehicleGatingManifest
def DamageModel = Definition.asInstanceOf[DamageResistanceModel] def DamageModel = Definition.asInstanceOf[DamageResistanceModel]
@ -565,11 +563,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* This is the definition entry that is used to store and unload pertinent information about the `Vehicle`. * This is the definition entry that is used to store and unload pertinent information about the `Vehicle`.
* @return the vehicle's definition entry * @return the vehicle's definition entry
*/ */
def Definition : VehicleDefinition = vehicleDef def Definition: VehicleDefinition = vehicleDef
def canEqual(other: Any): Boolean = other.isInstanceOf[Vehicle] def canEqual(other: Any): Boolean = other.isInstanceOf[Vehicle]
override def equals(other : Any) : Boolean = other match { override def equals(other: Any): Boolean =
other match {
case that: Vehicle => case that: Vehicle =>
(that canEqual this) && (that canEqual this) &&
hashCode() == that.hashCode() hashCode() == that.hashCode()
@ -577,18 +576,19 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
false false
} }
override def hashCode() : Int = Actor.hashCode() override def hashCode(): Int = Actor.hashCode()
/** /**
* Override the string representation to provide additional information. * Override the string representation to provide additional information.
* @return the string output * @return the string output
*/ */
override def toString : String = { override def toString: String = {
Vehicle.toString(this) Vehicle.toString(this)
} }
} }
object Vehicle { object Vehicle {
/** /**
* A basic `Trait` connecting all of the actionable `Vehicle` response messages. * A basic `Trait` connecting all of the actionable `Vehicle` response messages.
*/ */
@ -599,7 +599,7 @@ object Vehicle {
* @param player the player who sent this request message * @param player the player who sent this request message
* @param response the result of the processed request * @param response the result of the processed request
*/ */
final case class VehicleMessages(player : Player, response : Exchange) final case class VehicleMessages(player: Player, response: Exchange)
/** /**
* Initiate vehicle deconstruction. * Initiate vehicle deconstruction.
@ -607,7 +607,7 @@ object Vehicle {
* @param time the delay before deconstruction should initiate; * @param time the delay before deconstruction should initiate;
* should initiate instantly when `None` * should initiate instantly when `None`
*/ */
final case class Deconstruct(time : Option[FiniteDuration] = None) final case class Deconstruct(time: Option[FiniteDuration] = None)
/** /**
* The `Vehicle` will resume previous unresponsiveness to player activity. * The `Vehicle` will resume previous unresponsiveness to player activity.
@ -620,23 +620,23 @@ object Vehicle {
* @see `FacilityBenefitShieldChargeRequestMessage` * @see `FacilityBenefitShieldChargeRequestMessage`
* @param amount the number of points to charge * @param amount the number of points to charge
*/ */
final case class ChargeShields(amount : Int) final case class ChargeShields(amount: Int)
/** /**
* Following a successful shield charge tick, display the results of the update. * Following a successful shield charge tick, display the results of the update.
* @see `FacilityBenefitShieldChargeRequestMessage` * @see `FacilityBenefitShieldChargeRequestMessage`
* @param vehicle the updated vehicle * @param vehicle the updated vehicle
*/ */
final case class UpdateShieldsCharge(vehicle : Vehicle) final case class UpdateShieldsCharge(vehicle: Vehicle)
/** /**
* Change a vehicle's internal ownership property to match that of the target player. * Change a vehicle's internal ownership property to match that of the target player.
* @param player the person who will own the vehicle, or `None` if the vehicle will go unowned * @param player the person who will own the vehicle, or `None` if the vehicle will go unowned
*/ */
final case class Ownership(player : Option[Player]) final case class Ownership(player: Option[Player])
object Ownership { object Ownership {
def apply(player : Player) : Ownership = Ownership(Some(player)) def apply(player: Player): Ownership = Ownership(Some(player))
} }
/** /**
@ -644,7 +644,7 @@ object Vehicle {
* @param vehicleDef the vehicle's definition entry * @param vehicleDef the vehicle's definition entry
* @return a `Vehicle` object * @return a `Vehicle` object
*/ */
def apply(vehicleDef : VehicleDefinition) : Vehicle = { def apply(vehicleDef: VehicleDefinition): Vehicle = {
new Vehicle(vehicleDef) new Vehicle(vehicleDef)
} }
@ -652,8 +652,8 @@ object Vehicle {
* Given a `Map` of `Utility` objects, only return the objects with a positive or zero-index position. * Given a `Map` of `Utility` objects, only return the objects with a positive or zero-index position.
* @return a map of applicable utilities * @return a map of applicable utilities
*/ */
def EquipmentUtilities(utilities : Map[Int, Utility]) : Map[Int, Utility] = { def EquipmentUtilities(utilities: Map[Int, Utility]): Map[Int, Utility] = {
utilities.filter({ case(index : Int, _ : Utility) => index > -1 }) utilities.filter({ case (index: Int, _: Utility) => index > -1 })
} }
/** /**
@ -661,30 +661,35 @@ object Vehicle {
* @param vehicle the `Vehicle` being initialized * @param vehicle the `Vehicle` being initialized
* @see `{object}.LoadDefinition` * @see `{object}.LoadDefinition`
*/ */
def LoadDefinition(vehicle : Vehicle) : Vehicle = { def LoadDefinition(vehicle: Vehicle): Vehicle = {
val vdef : VehicleDefinition = vehicle.Definition val vdef: VehicleDefinition = vehicle.Definition
//general stuff //general stuff
vehicle.Health = vdef.DefaultHealth vehicle.Health = vdef.DefaultHealth
//create weapons //create weapons
vehicle.weapons = vdef.Weapons.map({case (num, definition) => vehicle.weapons = vdef.Weapons
.map({
case (num, definition) =>
val slot = EquipmentSlot(EquipmentSize.VehicleWeapon) val slot = EquipmentSlot(EquipmentSize.VehicleWeapon)
slot.Equipment = Tool(definition) slot.Equipment = Tool(definition)
num -> slot num -> slot
}).toMap })
.toMap
//create seats //create seats
vehicle.seats = vdef.Seats.map({ case(num, definition) => num -> Seat(definition)}).toMap vehicle.seats = vdef.Seats.map({ case (num, definition) => num -> Seat(definition) }).toMap
// create cargo holds // create cargo holds
vehicle.cargoHolds = vdef.Cargo.map({ case(num, definition) => num -> Cargo(definition)}).toMap vehicle.cargoHolds = vdef.Cargo.map({ case (num, definition) => num -> Cargo(definition) }).toMap
//create utilities //create utilities
vehicle.utilities = vdef.Utilities.map({ vehicle.utilities = vdef.Utilities
case(num, util) => .map({
case (num, util) =>
val obj = Utility(util, vehicle) val obj = Utility(util, vehicle)
val utilObj = obj() val utilObj = obj()
vehicle.Amenities = utilObj vehicle.Amenities = utilObj
utilObj.LocationOffset = vdef.UtilityOffset.get(num) utilObj.LocationOffset = vdef.UtilityOffset.get(num)
num -> obj num -> obj
}).toMap })
.toMap
//trunk //trunk
vdef.TrunkSize match { vdef.TrunkSize match {
case InventoryTile.None => ; case InventoryTile.None => ;
@ -699,7 +704,7 @@ object Vehicle {
* Provide a fixed string representation. * Provide a fixed string representation.
* @return the string output * @return the string output
*/ */
def toString(obj : Vehicle) : String = { def toString(obj: Vehicle): String = {
val occupancy = obj.Seats.values.count(seat => seat.isOccupied) val occupancy = obj.Seats.values.count(seat => seat.isOccupied)
s"${obj.Definition.Name}, owned by ${obj.Owner}: (${obj.Health}/${obj.MaxHealth})(${obj.Shields}/${obj.MaxShields}) ($occupancy)" s"${obj.Definition.Name}, owned by ${obj.Owner}: (${obj.Health}/${obj.MaxHealth})(${obj.Shields}/${obj.MaxShields}) ($occupancy)"
} }

View file

@ -20,7 +20,7 @@ object Vehicles {
* @param player na * @param player na
* @return na * @return na
*/ */
def Own(vehicle : Vehicle, player : Player) : Option[Vehicle] = Own(vehicle, Some(player)) def Own(vehicle: Vehicle, player: Player): Option[Vehicle] = Own(vehicle, Some(player))
/** /**
* na * na
@ -28,12 +28,15 @@ object Vehicles {
* @param playerOpt na * @param playerOpt na
* @return na * @return na
*/ */
def Own(vehicle : Vehicle, playerOpt : Option[Player]) : Option[Vehicle] = { def Own(vehicle: Vehicle, playerOpt: Option[Player]): Option[Vehicle] = {
playerOpt match { playerOpt match {
case Some(tplayer) => case Some(tplayer) =>
tplayer.VehicleOwned = vehicle.GUID tplayer.VehicleOwned = vehicle.GUID
vehicle.AssignOwnership(playerOpt) vehicle.AssignOwnership(playerOpt)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(vehicle.Zone.Id, VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)) vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
vehicle.Zone.Id,
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
)
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Name) Vehicles.ReloadAccessPermissions(vehicle, tplayer.Name)
Some(vehicle) Some(vehicle)
case None => case None =>
@ -48,18 +51,23 @@ object Vehicles {
* @return the vehicle, if it had a previous owner; * @return the vehicle, if it had a previous owner;
* `None`, otherwise * `None`, otherwise
*/ */
def Disown(guid : PlanetSideGUID, vehicle : Vehicle) : Option[Vehicle] = vehicle.Zone.GUID(vehicle.Owner) match { def Disown(guid: PlanetSideGUID, vehicle: Vehicle): Option[Vehicle] =
case Some(player : Player) => vehicle.Zone.GUID(vehicle.Owner) match {
if(player.VehicleOwned.contains(guid)) { case Some(player: Player) =>
if (player.VehicleOwned.contains(guid)) {
player.VehicleOwned = None player.VehicleOwned = None
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(player.GUID, PlanetSideGUID(0))) vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
player.Name,
VehicleAction.Ownership(player.GUID, PlanetSideGUID(0))
)
} }
vehicle.AssignOwnership(None) vehicle.AssignOwnership(None)
val empire = VehicleLockState.Empire.id val empire = VehicleLockState.Empire.id
val factionChannel = s"${vehicle.Faction}" val factionChannel = s"${vehicle.Faction}"
(0 to 2).foreach(group => { (0 to 2).foreach(group => {
vehicle.PermissionGroup(group, empire) vehicle.PermissionGroup(group, empire)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(factionChannel, vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
factionChannel,
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire) VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
) )
}) })
@ -76,7 +84,8 @@ object Vehicles {
* This is the player side of vehicle ownership removal. * This is the player side of vehicle ownership removal.
* @param player the player * @param player the player
*/ */
def Disown(player : Player, zone : Zone) : Option[Vehicle] = Disown(player, Some(zone)) def Disown(player: Player, zone: Zone): Option[Vehicle] = Disown(player, Some(zone))
/** /**
* Disassociate a player from a vehicle that he owns. * Disassociate a player from a vehicle that he owns.
* The vehicle must exist in the game world on the specified continent. * The vehicle must exist in the game world on the specified continent.
@ -84,12 +93,12 @@ object Vehicles {
* This is the player side of vehicle ownership removal. * This is the player side of vehicle ownership removal.
* @param player the player * @param player the player
*/ */
def Disown(player : Player, zoneOpt : Option[Zone]) : Option[Vehicle] = { def Disown(player: Player, zoneOpt: Option[Zone]): Option[Vehicle] = {
player.VehicleOwned match { player.VehicleOwned match {
case Some(vehicle_guid) => case Some(vehicle_guid) =>
player.VehicleOwned = None player.VehicleOwned = None
zoneOpt.getOrElse(player.Zone).GUID(vehicle_guid) match { zoneOpt.getOrElse(player.Zone).GUID(vehicle_guid) match {
case Some(vehicle : Vehicle) => case Some(vehicle: Vehicle) =>
Disown(player, vehicle) Disown(player, vehicle)
case _ => case _ =>
None None
@ -106,21 +115,23 @@ object Vehicles {
* This is the vehicle side of vehicle ownership removal. * This is the vehicle side of vehicle ownership removal.
* @param player the player * @param player the player
*/ */
def Disown(player : Player, vehicle : Vehicle) : Option[Vehicle] = { def Disown(player: Player, vehicle: Vehicle): Option[Vehicle] = {
val pguid = player.GUID val pguid = player.GUID
if(vehicle.Owner.contains(pguid)) { if (vehicle.Owner.contains(pguid)) {
vehicle.AssignOwnership(None) vehicle.AssignOwnership(None)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(pguid, PlanetSideGUID(0))) vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(pguid, PlanetSideGUID(0)))
val vguid = vehicle.GUID val vguid = vehicle.GUID
val empire = VehicleLockState.Empire.id val empire = VehicleLockState.Empire.id
(0 to 2).foreach(group => { (0 to 2).foreach(group => {
vehicle.PermissionGroup(group, empire) vehicle.PermissionGroup(group, empire)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(s"${vehicle.Faction}", VehicleAction.SeatPermissions(pguid, vguid, group, empire)) vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
s"${vehicle.Faction}",
VehicleAction.SeatPermissions(pguid, vguid, group, empire)
)
}) })
ReloadAccessPermissions(vehicle, player.Name) ReloadAccessPermissions(vehicle, player.Name)
Some(vehicle) Some(vehicle)
} } else {
else {
None None
} }
} }
@ -134,7 +145,7 @@ object Vehicles {
* The most important examples include either the player or the vehicle itself spawning in for the first time. * The most important examples include either the player or the vehicle itself spawning in for the first time.
* @param vehicle the `Vehicle` * @param vehicle the `Vehicle`
*/ */
def ReloadAccessPermissions(vehicle : Vehicle, toChannel : String) : Unit = { def ReloadAccessPermissions(vehicle: Vehicle, toChannel: String): Unit = {
val vehicle_guid = vehicle.GUID val vehicle_guid = vehicle.GUID
(0 to 3).foreach(group => { (0 to 3).foreach(group => {
vehicle.Zone.AvatarEvents ! AvatarServiceMessage( vehicle.Zone.AvatarEvents ! AvatarServiceMessage(
@ -170,7 +181,7 @@ object Vehicles {
* @return `true`, if all passengers of the vehicle, and its cargo vehicles, etc., have reported being in the same zone; * @return `true`, if all passengers of the vehicle, and its cargo vehicles, etc., have reported being in the same zone;
* `false`, if no manifest entry exists, or if the vehicle is moving to the same zone * `false`, if no manifest entry exists, or if the vehicle is moving to the same zone
*/ */
def AllGatedOccupantsInSameZone(vehicle : Vehicle) : Boolean = { def AllGatedOccupantsInSameZone(vehicle: Vehicle): Boolean = {
val vzone = vehicle.Zone val vzone = vehicle.Zone
vehicle.PreviousGatingManifest() match { vehicle.PreviousGatingManifest() match {
case Some(manifest) if vzone != manifest.origin => case Some(manifest) if vzone != manifest.origin =>
@ -192,11 +203,10 @@ object Vehicles {
* @return the orientation as an `Integer` value; * @return the orientation as an `Integer` value;
* `0` for almost all cases * `0` for almost all cases
*/ */
def CargoOrientation(vehicle : Vehicle) : Int = { def CargoOrientation(vehicle: Vehicle): Int = {
if(vehicle.Definition == GlobalDefinitions.router) { if (vehicle.Definition == GlobalDefinitions.router) {
1 1
} } else {
else {
0 0
} }
} }
@ -208,17 +218,22 @@ object Vehicles {
* @param hacker the one whoi performed the hack and will inherit ownership of the target vehicle * @param hacker the one whoi performed the hack and will inherit ownership of the target vehicle
* @param unk na; used by `HackMessage` as `unk5` * @param unk na; used by `HackMessage` as `unk5`
*/ */
def FinishHackingVehicle(target : Vehicle, hacker : Player, unk : Long)(): Unit = { def FinishHackingVehicle(target: Vehicle, hacker: Player, unk: Long)(): Unit = {
log.info(s"Vehicle guid: ${target.GUID} has been jacked") log.info(s"Vehicle guid: ${target.GUID} has been jacked")
import scala.concurrent.duration._
val zone = target.Zone val zone = target.Zone
// Forcefully dismount any cargo // Forcefully dismount any cargo
target.CargoHolds.values.foreach(cargoHold => { target.CargoHolds.values.foreach(cargoHold => {
cargoHold.Occupant match { cargoHold.Occupant match {
case Some(cargo : Vehicle) => { case Some(cargo: Vehicle) => {
cargo.Seats(0).Occupant match { cargo.Seats(0).Occupant match {
case Some(cargoDriver: Player) => case Some(cargoDriver: Player) =>
CargoBehavior.HandleVehicleCargoDismount(target.Zone, cargo.GUID, bailed = target.Flying, requestedByPassenger = false, kicked = true ) CargoBehavior.HandleVehicleCargoDismount(
target.Zone,
cargo.GUID,
bailed = target.Flying,
requestedByPassenger = false,
kicked = true
)
case None => case None =>
log.error("FinishHackingVehicle: vehicle in cargo hold missing driver") log.error("FinishHackingVehicle: vehicle in cargo hold missing driver")
CargoBehavior.HandleVehicleCargoDismount(cargo.GUID, cargo, target.GUID, target, false, false, true) CargoBehavior.HandleVehicleCargoDismount(cargo.GUID, cargo, target.GUID, target, false, false, true)
@ -233,20 +248,23 @@ object Vehicles {
case Some(tplayer) => case Some(tplayer) =>
seat.Occupant = None seat.Occupant = None
tplayer.VehicleSeated = None tplayer.VehicleSeated = None
if(tplayer.HasGUID) { if (tplayer.HasGUID) {
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID)) zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID)
)
} }
case None => ; case None => ;
} }
}) })
// If the vehicle can fly and is flying deconstruct it, and well played to whomever managed to hack a plane in mid air. I'm impressed. // If the vehicle can fly and is flying deconstruct it, and well played to whomever managed to hack a plane in mid air. I'm impressed.
if(target.Definition.CanFly && target.Flying) { if (target.Definition.CanFly && target.Flying) {
// todo: Should this force the vehicle to land in the same way as when a pilot bails with passengers on board? // todo: Should this force the vehicle to land in the same way as when a pilot bails with passengers on board?
target.Actor ! Vehicle.Deconstruct() target.Actor ! Vehicle.Deconstruct()
} else { // Otherwise handle ownership transfer as normal } else { // Otherwise handle ownership transfer as normal
// Remove ownership of our current vehicle, if we have one // Remove ownership of our current vehicle, if we have one
hacker.VehicleOwned match { hacker.VehicleOwned match {
case Some(guid : PlanetSideGUID) => case Some(guid: PlanetSideGUID) =>
zone.GUID(guid) match { zone.GUID(guid) match {
case Some(vehicle: Vehicle) => case Some(vehicle: Vehicle) =>
Vehicles.Disown(hacker, vehicle) Vehicles.Disown(hacker, vehicle)
@ -270,9 +288,15 @@ object Vehicles {
Vehicles.Own(target, hacker) Vehicles.Own(target, hacker)
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary. //todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
// And broadcast the faction change to other clients // And broadcast the faction change to other clients
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction)) zone.AvatarEvents ! AvatarServiceMessage(
zone.Id,
AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction)
)
} }
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)) zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
)
// Clean up after specific vehicles, e.g. remove router telepads // Clean up after specific vehicles, e.g. remove router telepads
// If AMS is deployed, swap it to the new faction // If AMS is deployed, swap it to the new faction
target.Definition match { target.Definition match {

View file

@ -7,13 +7,14 @@ import scala.collection.mutable
object Certification { object Certification {
object Dependencies { object Dependencies {
/** /**
* Find the certifications that are immediately dependent on the target certification. * Find the certifications that are immediately dependent on the target certification.
* (For `A`, find all `B` that are `B ⇒ A`.) * (For `A`, find all `B` that are `B ⇒ A`.)
* @param certification the target certification * @param certification the target certification
* @return all connected certifications * @return all connected certifications
*/ */
def From(certification : CertificationType.Value) : Set[CertificationType.Value] = dependencies(certification).toSet def From(certification: CertificationType.Value): Set[CertificationType.Value] = dependencies(certification).toSet
/** /**
* Find all certifications that are dependent on the target certification. * Find all certifications that are dependent on the target certification.
@ -21,14 +22,13 @@ object Certification {
* @param certification the target certification * @param certification the target certification
* @return all connected certifications * @return all connected certifications
*/ */
def FromAll(certification : CertificationType.Value) : Set[CertificationType.Value] = { def FromAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
var available : List[CertificationType.Value] = List(certification) var available: List[CertificationType.Value] = List(certification)
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value] var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
do { do {
available = available.flatMap(cert => dependencies(cert)) available = available.flatMap(cert => dependencies(cert))
allocated ++= available allocated ++= available
} } while (available.nonEmpty)
while(available.nonEmpty)
allocated.toSet allocated.toSet
} }
@ -38,7 +38,7 @@ object Certification {
* @param certification the target certification * @param certification the target certification
* @return all connected certifications * @return all connected certifications
*/ */
def For(certification : CertificationType.Value) : Set[CertificationType.Value] = { def For(certification: CertificationType.Value): Set[CertificationType.Value] = {
(for { (for {
(cert, certs) <- dependencies (cert, certs) <- dependencies
if certs contains certification if certs contains certification
@ -51,16 +51,15 @@ object Certification {
* @param certification the target certification * @param certification the target certification
* @return all connected certifications * @return all connected certifications
*/ */
def ForAll(certification : CertificationType.Value) : Set[CertificationType.Value] = { def ForAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
var available : List[CertificationType.Value] = List(certification) var available: List[CertificationType.Value] = List(certification)
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value] var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
do { do {
available = available.flatMap { available = available.flatMap {
For For
} }
allocated ++= available allocated ++= available
} } while (available.nonEmpty)
while(available.nonEmpty)
allocated.toSet allocated.toSet
} }
@ -72,7 +71,8 @@ object Certification {
* @param certification the target certification * @param certification the target certification
* @return all connected certifications * @return all connected certifications
*/ */
def Like(certification : CertificationType.Value) : Set[CertificationType.Value] = certification match { def Like(certification: CertificationType.Value): Set[CertificationType.Value] =
certification match {
case AssaultBuggy => case AssaultBuggy =>
Set(Harasser) Set(Harasser)
case LightScout => case LightScout =>
@ -87,7 +87,7 @@ object Certification {
Set.empty[CertificationType.Value] Set.empty[CertificationType.Value]
} }
private val dependencies : Map[CertificationType.Value, List[CertificationType.Value]] = Map( private val dependencies: Map[CertificationType.Value, List[CertificationType.Value]] = Map(
StandardAssault -> List(), StandardAssault -> List(),
AgileExoSuit -> List(), AgileExoSuit -> List(),
ReinforcedExoSuit -> List(), ReinforcedExoSuit -> List(),
@ -96,7 +96,6 @@ object Certification {
AVMAX -> List(), AVMAX -> List(),
AAMAX -> List(), AAMAX -> List(),
UniMAX -> List(), UniMAX -> List(),
StandardAssault -> List(), StandardAssault -> List(),
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault), MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
AntiVehicular -> List(), AntiVehicular -> List(),
@ -104,7 +103,6 @@ object Certification {
Sniping -> List(), Sniping -> List(),
SpecialAssault -> List(EliteAssault), SpecialAssault -> List(EliteAssault),
EliteAssault -> List(), EliteAssault -> List(),
ATV -> List(Switchblade), ATV -> List(Switchblade),
Switchblade -> List(), Switchblade -> List(),
Harasser -> List(), Harasser -> List(),
@ -115,18 +113,15 @@ object Certification {
ArmoredAssault1 -> List(ArmoredAssault2), ArmoredAssault1 -> List(ArmoredAssault2),
ArmoredAssault2 -> List(BattleFrameRobotics, Flail), ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
Flail -> List(), Flail -> List(),
AirCavalryScout -> List(AirCavalryAssault), AirCavalryScout -> List(AirCavalryAssault),
AirCavalryAssault -> List(AirCavalryInterceptor), AirCavalryAssault -> List(AirCavalryInterceptor),
AirCavalryInterceptor -> List(), AirCavalryInterceptor -> List(),
AirSupport -> List(GalaxyGunship), AirSupport -> List(GalaxyGunship),
GalaxyGunship -> List(), GalaxyGunship -> List(),
Phantasm -> List(), Phantasm -> List(),
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft), BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
BFRAntiInfantry -> List(), BFRAntiInfantry -> List(),
BFRAntiAircraft -> List(), BFRAntiAircraft -> List(),
Medical -> List(AdvancedMedical), Medical -> List(AdvancedMedical),
AdvancedMedical -> List(), AdvancedMedical -> List(),
Engineering -> List(CombatEngineering), Engineering -> List(CombatEngineering),
@ -143,12 +138,13 @@ object Certification {
} }
object Cost { object Cost {
/** /**
* For a certification, get its point cost. * For a certification, get its point cost.
* @param certification the certification * @param certification the certification
* @return the cost * @return the cost
*/ */
def Of(certification : CertificationType.Value) : Int = points(certification) def Of(certification: CertificationType.Value): Int = points(certification)
/** /**
* For a list of certifications, find the point cost of all unique certifications. * For a list of certifications, find the point cost of all unique certifications.
@ -156,7 +152,7 @@ object Certification {
* @param certifications the certification list * @param certifications the certification list
* @return the total cost * @return the total cost
*/ */
def Of(certifications : List[CertificationType.Value]) : Int = Of(certifications.toSet) def Of(certifications: List[CertificationType.Value]): Int = Of(certifications.toSet)
/** /**
* For a set of certifications, find the point cost of all certifications. * For a set of certifications, find the point cost of all certifications.
@ -164,19 +160,19 @@ object Certification {
* @param certifications the certification list * @param certifications the certification list
* @return the total cost * @return the total cost
*/ */
def Of(certifications : Set[CertificationType.Value]) : Int = OfAll(certifications.toList) def Of(certifications: Set[CertificationType.Value]): Int = OfAll(certifications.toList)
/** /**
* For a list of certifications, find the point cost of all certifications, counting any duplicates. * For a list of certifications, find the point cost of all certifications, counting any duplicates.
* @param certifications the certification list * @param certifications the certification list
* @return the total cost * @return the total cost
*/ */
def OfAll(certifications : List[CertificationType.Value]) : Int = { def OfAll(certifications: List[CertificationType.Value]): Int = {
certifications map points sum certifications map points sum
} }
import CertificationType._ import CertificationType._
private val points : Map[CertificationType.Value, Int] = Map( private val points: Map[CertificationType.Value, Int] = Map(
StandardExoSuit -> 0, StandardExoSuit -> 0,
AgileExoSuit -> 0, AgileExoSuit -> 0,
ReinforcedExoSuit -> 3, ReinforcedExoSuit -> 3,
@ -185,7 +181,6 @@ object Certification {
AIMAX -> 3, AIMAX -> 3,
AVMAX -> 3, AVMAX -> 3,
UniMAX -> 6, UniMAX -> 6,
StandardAssault -> 0, StandardAssault -> 0,
MediumAssault -> 2, MediumAssault -> 2,
AntiVehicular -> 3, AntiVehicular -> 3,
@ -193,7 +188,6 @@ object Certification {
Sniping -> 3, Sniping -> 3,
SpecialAssault -> 3, SpecialAssault -> 3,
EliteAssault -> 1, EliteAssault -> 1,
ATV -> 1, ATV -> 1,
Switchblade -> 1, Switchblade -> 1,
Harasser -> 1, Harasser -> 1,
@ -204,18 +198,15 @@ object Certification {
ArmoredAssault1 -> 2, ArmoredAssault1 -> 2,
ArmoredAssault2 -> 3, ArmoredAssault2 -> 3,
Flail -> 1, Flail -> 1,
AirCavalryScout -> 3, AirCavalryScout -> 3,
AirCavalryAssault -> 2, AirCavalryAssault -> 2,
AirCavalryInterceptor -> 2, AirCavalryInterceptor -> 2,
AirSupport -> 3, AirSupport -> 3,
GalaxyGunship -> 2, GalaxyGunship -> 2,
Phantasm -> 3, Phantasm -> 3,
BattleFrameRobotics -> 4, BattleFrameRobotics -> 4,
BFRAntiInfantry -> 1, BFRAntiInfantry -> 1,
BFRAntiAircraft -> 1, BFRAntiAircraft -> 1,
Medical -> 3, Medical -> 3,
AdvancedMedical -> 2, AdvancedMedical -> 2,
Engineering -> 3, Engineering -> 3,

View file

@ -11,15 +11,14 @@ import net.psforever.types.{PlanetSideEmpire, Vector3}
import services.Service import services.Service
import services.avatar.{AvatarAction, AvatarServiceMessage} import services.avatar.{AvatarAction, AvatarServiceMessage}
class CorpseControl(player : Player) extends Actor class CorpseControl(player: Player) extends Actor with ContainableBehavior {
with ContainableBehavior {
def ContainerObject = player def ContainerObject = player
//private [this] val log = org.log4s.getLogger(player.Name) //private [this] val log = org.log4s.getLogger(player.Name)
def receive : Receive = containerBehavior.orElse { case _ => ; } def receive: Receive = containerBehavior.orElse { case _ => ; }
def MessageDeferredCallback(msg : Any) : Unit = { def MessageDeferredCallback(msg: Any): Unit = {
msg match { msg match {
case Containable.MoveItem(_, item, _) => case Containable.MoveItem(_, item, _) =>
//momentarily put item back where it was originally //momentarily put item back where it was originally
@ -36,7 +35,7 @@ class CorpseControl(player : Player) extends Actor
} }
} }
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = { def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
val obj = ContainerObject val obj = ContainerObject
val zone = obj.Zone val zone = obj.Zone
val events = zone.AvatarEvents val events = zone.AvatarEvents
@ -44,7 +43,7 @@ class CorpseControl(player : Player) extends Actor
events ! AvatarServiceMessage(zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID)) events ! AvatarServiceMessage(zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
} }
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = { def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
val obj = ContainerObject val obj = ContainerObject
val zone = obj.Zone val zone = obj.Zone
val events = zone.AvatarEvents val events = zone.AvatarEvents
@ -63,10 +62,11 @@ class CorpseControl(player : Player) extends Actor
) )
} }
def SwapItemCallback(item : Equipment) : Unit = { def SwapItemCallback(item: Equipment): Unit = {
val obj = ContainerObject val obj = ContainerObject
val zone = obj.Zone val zone = obj.Zone
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, zone.AvatarEvents ! AvatarServiceMessage(
zone.Id,
AvatarAction.SendResponse( AvatarAction.SendResponse(
Service.defaultPlayerGUID, Service.defaultPlayerGUID,
ObjectDetachMessage(obj.GUID, item.GUID, Vector3.Zero, 0f) ObjectDetachMessage(obj.GUID, item.GUID, Vector3.Zero, 0f)

View file

@ -23,29 +23,36 @@ import scala.collection.mutable
* these structures are updated to reflect proper count. * these structures are updated to reflect proper count.
*/ */
class DeployableToolbox { class DeployableToolbox {
/** /**
* a map of bins for keeping track of the quantities of deployables in a category * a map of bins for keeping track of the quantities of deployables in a category
* keys: categories, values: quantity storage object * keys: categories, values: quantity storage object
*/ */
private val categoryCounts = DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap private val categoryCounts =
DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
categoryCounts(DeployableCategory.Telepads).Max = 1024 categoryCounts(DeployableCategory.Telepads).Max = 1024
/** /**
* a map of bins for keeping track of the quantities of individual deployables * a map of bins for keeping track of the quantities of individual deployables
* keys: deployable types, values: quantity storage object * keys: deployable types, values: quantity storage object
*/ */
private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
deployableCounts(DeployedItem.router_telepad_deployable).Max = 1024 deployableCounts(DeployedItem.router_telepad_deployable).Max = 1024
/** /**
* a map of tracked/owned individual deployables * a map of tracked/owned individual deployables
* keys: categories, values: deployable objects * keys: categories, values: deployable objects
*/ */
private val deployableLists = private val deployableLists =
DeployableCategory.values.toSeq.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() }).toMap DeployableCategory.values.toSeq
.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() })
.toMap
/** /**
* can only be initialized once * can only be initialized once
* set during the `Initialization` method primarily, and in `Add` and in `Remove` if not * set during the `Initialization` method primarily, and in `Add` and in `Remove` if not
*/ */
private var initialized : Boolean = false private var initialized: Boolean = false
/** /**
* Set up the initial deployable counts by providing certification values to be used in category and unit selection. * Set up the initial deployable counts by providing certification values to be used in category and unit selection.
@ -53,13 +60,12 @@ class DeployableToolbox {
* @return `true`, if this is the first time and actual "initialization" is performed; * @return `true`, if this is the first time and actual "initialization" is performed;
* `false`, otherwise * `false`, otherwise
*/ */
def Initialize(certifications : Set[CertificationType.Value]) : Boolean = { def Initialize(certifications: Set[CertificationType.Value]): Boolean = {
if(!initialized) { if (!initialized) {
DeployableToolbox.Initialize(deployableCounts, categoryCounts, certifications) DeployableToolbox.Initialize(deployableCounts, categoryCounts, certifications)
initialized = true initialized = true
true true
} } else {
else {
false false
} }
} }
@ -72,7 +78,10 @@ class DeployableToolbox {
* occasionally, important former certification values are required for additional configuration; * occasionally, important former certification values are required for additional configuration;
* the new certification should already have been added to this group * the new certification should already have been added to this group
*/ */
def AddToDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = { def AddToDeployableQuantities(
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
initialized = true initialized = true
DeployableToolbox.AddToDeployableQuantities(deployableCounts, categoryCounts, certification, certificationSet) DeployableToolbox.AddToDeployableQuantities(deployableCounts, categoryCounts, certification, certificationSet)
} }
@ -86,7 +95,10 @@ class DeployableToolbox {
* occasionally, important former certification values are required for additional configuration; * occasionally, important former certification values are required for additional configuration;
* the new certification should already have been excluded from this group * the new certification should already have been excluded from this group
*/ */
def RemoveFromDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = { def RemoveFromDeployableQuantities(
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
initialized = true initialized = true
DeployableToolbox.RemoveFromDeployablesQuantities(deployableCounts, categoryCounts, certification, certificationSet) DeployableToolbox.RemoveFromDeployablesQuantities(deployableCounts, categoryCounts, certification, certificationSet)
} }
@ -100,7 +112,7 @@ class DeployableToolbox {
* @return `true`, if it can be managed under the current conditions; * @return `true`, if it can be managed under the current conditions;
* `false`, otherwise * `false`, otherwise
*/ */
def Accept(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Accept(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
Valid(obj) && Available(obj) && !Contains(obj) Valid(obj) && Available(obj) && !Contains(obj)
} }
@ -111,7 +123,7 @@ class DeployableToolbox {
* @return `true`, if both category maximum and deployable type maximum are positive non-zero integers; * @return `true`, if both category maximum and deployable type maximum are positive non-zero integers;
* `false`, otherwise * `false`, otherwise
*/ */
def Valid(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Valid(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Max > 0 && deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Max > 0 &&
categoryCounts(obj.Definition.DeployCategory).Max > 0 categoryCounts(obj.Definition.DeployCategory).Max > 0
} }
@ -124,7 +136,7 @@ class DeployableToolbox {
* @return `true`, if the deployable can be added to the support lists and counted; * @return `true`, if the deployable can be added to the support lists and counted;
* `false`, otherwise * `false`, otherwise
*/ */
def Available(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Available(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available && deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available &&
categoryCounts(obj.Definition.DeployCategory).Available categoryCounts(obj.Definition.DeployCategory).Available
} }
@ -136,7 +148,7 @@ class DeployableToolbox {
* @return `true`, if the deployable can be found in one of the lists; * @return `true`, if the deployable can be found in one of the lists;
* `false`, otherwise * `false`, otherwise
*/ */
def Contains(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Contains(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableLists(obj.Definition.DeployCategory).contains(obj) deployableLists(obj.Definition.DeployCategory).contains(obj)
} }
@ -152,18 +164,17 @@ class DeployableToolbox {
* @return `true`, if the deployable is added; * @return `true`, if the deployable is added;
* `false`, otherwise * `false`, otherwise
*/ */
def Add(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Add(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
val category = obj.Definition.DeployCategory val category = obj.Definition.DeployCategory
val dCategory = categoryCounts(category) val dCategory = categoryCounts(category)
val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)) val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item))
val dList = deployableLists(category) val dList = deployableLists(category)
if(dCategory.Available() && dType.Available() && !dList.contains(obj)) { if (dCategory.Available() && dType.Available() && !dList.contains(obj)) {
dCategory.Current += 1 dCategory.Current += 1
dType.Current += 1 dType.Current += 1
dList += obj dList += obj
true true
} } else {
else {
false false
} }
} }
@ -179,16 +190,15 @@ class DeployableToolbox {
* @return `true`, if the deployable is added; * @return `true`, if the deployable is added;
* `false`, otherwise * `false`, otherwise
*/ */
def Remove(obj : DeployableToolbox.AcceptableDeployable) : Boolean = { def Remove(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
val category = obj.Definition.DeployCategory val category = obj.Definition.DeployCategory
val deployables = deployableLists(category) val deployables = deployableLists(category)
if(deployables.contains(obj)) { if (deployables.contains(obj)) {
categoryCounts(category).Current -= 1 categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Current -= 1 deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Current -= 1
deployables -= obj deployables -= obj
true true
} } else {
else {
false false
} }
} }
@ -199,7 +209,7 @@ class DeployableToolbox {
* @param obj the example deployable * @param obj the example deployable
* @return any deployable that is found * @return any deployable that is found
*/ */
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable) : Option[DeployableToolbox.AcceptableDeployable] = { def DisplaceFirst(obj: DeployableToolbox.AcceptableDeployable): Option[DeployableToolbox.AcceptableDeployable] = {
DisplaceFirst(obj, { d => d.Definition.Item == obj.Definition.Item }) DisplaceFirst(obj, { d => d.Definition.Item == obj.Definition.Item })
} }
@ -213,11 +223,14 @@ class DeployableToolbox {
* @param rule the testing rule for determining a valid deployable * @param rule the testing rule for determining a valid deployable
* @return any deployable that is found * @return any deployable that is found
*/ */
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable, rule : (Deployable)=> Boolean) : Option[DeployableToolbox.AcceptableDeployable] = { def DisplaceFirst(
obj: DeployableToolbox.AcceptableDeployable,
rule: (Deployable) => Boolean
): Option[DeployableToolbox.AcceptableDeployable] = {
val definition = obj.Definition val definition = obj.Definition
val category = definition.DeployCategory val category = definition.DeployCategory
val categoryList = deployableLists(category) val categoryList = deployableLists(category)
if(categoryList.nonEmpty) { if (categoryList.nonEmpty) {
val found = categoryList.find(rule) match { val found = categoryList.find(rule) match {
case Some(target) => case Some(target) =>
categoryList.remove(categoryList.indexOf(target)) categoryList.remove(categoryList.indexOf(target))
@ -227,8 +240,7 @@ class DeployableToolbox {
categoryCounts(category).Current -= 1 categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1 deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
Some(found) Some(found)
} } else {
else {
None None
} }
} }
@ -239,15 +251,14 @@ class DeployableToolbox {
* @param category the target category * @param category the target category
* @return any deployable that is found * @return any deployable that is found
*/ */
def DisplaceFirst(category : DeployableCategory.Value) : Option[DeployableToolbox.AcceptableDeployable] = { def DisplaceFirst(category: DeployableCategory.Value): Option[DeployableToolbox.AcceptableDeployable] = {
val categoryList = deployableLists(category) val categoryList = deployableLists(category)
if(categoryList.nonEmpty) { if (categoryList.nonEmpty) {
val found = categoryList.remove(0) val found = categoryList.remove(0)
categoryCounts(category).Current -= 1 categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1 deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
Some(found) Some(found)
} } else {
else {
None None
} }
} }
@ -257,7 +268,7 @@ class DeployableToolbox {
* @param filter the example deployable * @param filter the example deployable
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def Deployables(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = { def Deployables(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
Deployables(filter.Definition.Item) Deployables(filter.Definition.Item)
} }
@ -266,10 +277,11 @@ class DeployableToolbox {
* @param filter the type of deployable * @param filter the type of deployable
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def Deployables(filter : DeployedItem.Value) : List[PlanetSideGUID] = { def Deployables(filter: DeployedItem.Value): List[PlanetSideGUID] = {
deployableLists(Deployable.Category.Of(filter)) deployableLists(Deployable.Category.Of(filter))
.filter(entry => { entry.Definition.Item == filter }) .filter(entry => { entry.Definition.Item == filter })
.map(_.GUID).toList .map(_.GUID)
.toList
} }
/** /**
@ -277,7 +289,7 @@ class DeployableToolbox {
* @param filter the example deployable * @param filter the example deployable
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def Category(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = { def Category(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
Category(filter.Definition.DeployCategory) Category(filter.Definition.DeployCategory)
} }
@ -286,7 +298,7 @@ class DeployableToolbox {
* @param filter the type of deployable * @param filter the type of deployable
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def Category(filter : DeployableCategory.Value) : List[PlanetSideGUID] = { def Category(filter: DeployableCategory.Value): List[PlanetSideGUID] = {
deployableLists(filter).map(_.GUID).toList deployableLists(filter).map(_.GUID).toList
} }
@ -295,7 +307,7 @@ class DeployableToolbox {
* @param item the example deployable * @param item the example deployable
* @return the current quantity of deployables and the maximum number * @return the current quantity of deployables and the maximum number
*/ */
def CountDeployable(item : DeployedItem.Value) : (Int, Int) = { def CountDeployable(item: DeployedItem.Value): (Int, Int) = {
val dType = deployableCounts(DeployableToolbox.UnifiedType(item)) val dType = deployableCounts(DeployableToolbox.UnifiedType(item))
(dType.Current, dType.Max) (dType.Current, dType.Max)
} }
@ -305,21 +317,21 @@ class DeployableToolbox {
* @param item the example deployable * @param item the example deployable
* @return the current quantity of deployables and the maximum number * @return the current quantity of deployables and the maximum number
*/ */
def CountCategory(item : DeployedItem.Value) : (Int, Int) = { def CountCategory(item: DeployedItem.Value): (Int, Int) = {
val dCat = categoryCounts(Deployable.Category.Of(DeployableToolbox.UnifiedType(item))) val dCat = categoryCounts(Deployable.Category.Of(DeployableToolbox.UnifiedType(item)))
(dCat.Current, dCat.Max) (dCat.Current, dCat.Max)
} }
def UpdateUIElement(entry : DeployedItem.Value) : List[(Int,Int,Int,Int)] = { def UpdateUIElement(entry: DeployedItem.Value): List[(Int, Int, Int, Int)] = {
val toEntry = DeployableToolbox.UnifiedType(entry) val toEntry = DeployableToolbox.UnifiedType(entry)
val (curr, max) = Deployable.UI(toEntry) val (curr, max) = Deployable.UI(toEntry)
val dType = deployableCounts(toEntry) val dType = deployableCounts(toEntry)
List((curr, dType.Current, max, dType.Max)) List((curr, dType.Current, max, dType.Max))
} }
def UpdateUI() : List[(Int,Int,Int,Int)] = DeployedItem.values flatMap UpdateUIElement toList def UpdateUI(): List[(Int, Int, Int, Int)] = DeployedItem.values flatMap UpdateUIElement toList
def UpdateUI(entry : CertificationType.Value) : List[(Int,Int,Int,Int)] = { def UpdateUI(entry: CertificationType.Value): List[(Int, Int, Int, Int)] = {
import CertificationType._ import CertificationType._
entry match { entry match {
case AdvancedHacking => case AdvancedHacking =>
@ -327,19 +339,26 @@ class DeployableToolbox {
case CombatEngineering => case CombatEngineering =>
List( List(
DeployedItem.boomer, DeployedItem.he_mine, DeployedItem.spitfire_turret, DeployedItem.motionalarmsensor DeployedItem.boomer,
DeployedItem.he_mine,
DeployedItem.spitfire_turret,
DeployedItem.motionalarmsensor
) flatMap UpdateUIElement ) flatMap UpdateUIElement
case AssaultEngineering => case AssaultEngineering =>
List( List(
DeployedItem.jammer_mine, DeployedItem.portable_manned_turret, DeployedItem.deployable_shield_generator DeployedItem.jammer_mine,
DeployedItem.portable_manned_turret,
DeployedItem.deployable_shield_generator
) flatMap UpdateUIElement ) flatMap UpdateUIElement
case FortificationEngineering => case FortificationEngineering =>
List( List(
DeployedItem.boomer, DeployedItem.boomer,
DeployedItem.he_mine, DeployedItem.he_mine,
DeployedItem.spitfire_turret, DeployedItem.spitfire_cloaked, DeployedItem.spitfire_aa, DeployedItem.spitfire_turret,
DeployedItem.spitfire_cloaked,
DeployedItem.spitfire_aa,
DeployedItem.motionalarmsensor, DeployedItem.motionalarmsensor,
DeployedItem.tank_traps DeployedItem.tank_traps
) flatMap UpdateUIElement ) flatMap UpdateUIElement
@ -352,7 +371,7 @@ class DeployableToolbox {
} }
} }
def UpdateUI(certifications : List[CertificationType.Value]) : List[(Int,Int,Int,Int)] = { def UpdateUI(certifications: List[CertificationType.Value]): List[(Int, Int, Int, Int)] = {
certifications flatMap UpdateUI certifications flatMap UpdateUI
} }
@ -361,7 +380,7 @@ class DeployableToolbox {
* @param item the deployable type * @param item the deployable type
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def ClearDeployable(item : DeployedItem.Value) : List[PlanetSideGUID] = { def ClearDeployable(item: DeployedItem.Value): List[PlanetSideGUID] = {
val uitem = DeployableToolbox.UnifiedType(item) val uitem = DeployableToolbox.UnifiedType(item)
val category = Deployable.Category.Of(uitem) val category = Deployable.Category.Of(uitem)
val categoryList = deployableLists(category) val categoryList = deployableLists(category)
@ -379,13 +398,13 @@ class DeployableToolbox {
* @param item the deployable type belonging to a category * @param item the deployable type belonging to a category
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def ClearCategory(item : DeployedItem.Value) : List[PlanetSideGUID] = { def ClearCategory(item: DeployedItem.Value): List[PlanetSideGUID] = {
val category = Deployable.Category.Of(DeployableToolbox.UnifiedType(item)) val category = Deployable.Category.Of(DeployableToolbox.UnifiedType(item))
val out = deployableLists(category).map(_.GUID).toList val out = deployableLists(category).map(_.GUID).toList
deployableLists(category).clear() deployableLists(category).clear()
categoryCounts(category).Current = 0 categoryCounts(category).Current = 0
(Deployable.Category.Includes(category) map DeployableToolbox.UnifiedType toSet) (Deployable.Category.Includes(category) map DeployableToolbox.UnifiedType toSet)
.foreach({item : DeployedItem.Value => deployableCounts(item).Current = 0 }) .foreach({ item: DeployedItem.Value => deployableCounts(item).Current = 0 })
out out
} }
@ -393,7 +412,7 @@ class DeployableToolbox {
* Remove all managed deployables. * Remove all managed deployables.
* @return a list of globally unique identifiers that should be valid for the current zone * @return a list of globally unique identifiers that should be valid for the current zone
*/ */
def Clear() : List[PlanetSideGUID] = { def Clear(): List[PlanetSideGUID] = {
val out = deployableLists.values.flatten.map(_.GUID).toList val out = deployableLists.values.flatten.map(_.GUID).toList
deployableLists.values.foreach(_.clear()) deployableLists.values.foreach(_.clear())
deployableCounts.values.foreach(_.Current = 0) deployableCounts.values.foreach(_.Current = 0)
@ -403,6 +422,7 @@ class DeployableToolbox {
} }
object DeployableToolbox { object DeployableToolbox {
/** /**
* A `type` intended to properly define the minimum acceptable conditions for a `Deployable` object. * A `type` intended to properly define the minimum acceptable conditions for a `Deployable` object.
*/ */
@ -413,26 +433,28 @@ object DeployableToolbox {
* There are deployable numbers organized by deploybale type and by deployable category. * There are deployable numbers organized by deploybale type and by deployable category.
*/ */
private class Bin { private class Bin {
/** the maximum number of deployables for this criteria that can be managed */ /** the maximum number of deployables for this criteria that can be managed */
private var max : Int = 0 private var max: Int = 0
/** the current number of deployables for this criteria that are being managed */ /** the current number of deployables for this criteria that are being managed */
private var current : Int = 0 private var current: Int = 0
def Current : Int = current def Current: Int = current
def Current_=(curr : Int) : Int = { def Current_=(curr: Int): Int = {
current = curr current = curr
Current Current
} }
def Max : Int = max def Max: Int = max
def Max_=(mx : Int) : Int = { def Max_=(mx: Int): Int = {
max = mx max = mx
Max Max
} }
def Available() : Boolean = current < max def Available(): Boolean = current < max
} }
/** /**
@ -441,8 +463,10 @@ object DeployableToolbox {
* @param item the type of deployable * @param item the type of deployable
* @return the corrected deployable type * @return the corrected deployable type
*/ */
def UnifiedType(item : DeployedItem.Value) : DeployedItem.Value = item match { def UnifiedType(item: DeployedItem.Value): DeployedItem.Value =
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr | DeployedItem.portable_manned_turret_vs => item match {
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr |
DeployedItem.portable_manned_turret_vs =>
DeployedItem.portable_manned_turret DeployedItem.portable_manned_turret
case _ => case _ =>
item item
@ -454,9 +478,13 @@ object DeployableToolbox {
* @param categories a reference to the category `Bin` object * @param categories a reference to the category `Bin` object
* @param certifications a group of certifications for the initial values * @param certifications a group of certifications for the initial values
*/ */
private def Initialize(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certifications : Set[CertificationType.Value]) : Unit = { private def Initialize(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certifications: Set[CertificationType.Value]
): Unit = {
import CertificationType._ import CertificationType._
if(certifications.contains(AdvancedEngineering)) { if (certifications.contains(AdvancedEngineering)) {
counts(DeployedItem.boomer).Max = 25 counts(DeployedItem.boomer).Max = 25
counts(DeployedItem.he_mine).Max = 25 counts(DeployedItem.he_mine).Max = 25
counts(DeployedItem.jammer_mine).Max = 20 counts(DeployedItem.jammer_mine).Max = 20
@ -478,12 +506,11 @@ object DeployableToolbox {
categories(DeployableCategory.FieldTurrets).Max = 1 categories(DeployableCategory.FieldTurrets).Max = 1
categories(DeployableCategory.ShieldGenerators).Max = 1 categories(DeployableCategory.ShieldGenerators).Max = 1
if(certifications.contains(AdvancedHacking)) { if (certifications.contains(AdvancedHacking)) {
counts(DeployedItem.sensor_shield).Max = 25 counts(DeployedItem.sensor_shield).Max = 25
} }
} } else if (certifications.contains(CombatEngineering)) {
else if(certifications.contains(CombatEngineering)) { if (certifications.contains(AssaultEngineering)) {
if(certifications.contains(AssaultEngineering)) {
counts(DeployedItem.jammer_mine).Max = 20 counts(DeployedItem.jammer_mine).Max = 20
counts(DeployedItem.portable_manned_turret).Max = 1 //the below turret types are unified counts(DeployedItem.portable_manned_turret).Max = 1 //the below turret types are unified
//counts(DeployedItem.portable_manned_turret_nc).Max = 1 //counts(DeployedItem.portable_manned_turret_nc).Max = 1
@ -493,7 +520,7 @@ object DeployableToolbox {
categories(DeployableCategory.FieldTurrets).Max = 1 categories(DeployableCategory.FieldTurrets).Max = 1
categories(DeployableCategory.ShieldGenerators).Max = 1 categories(DeployableCategory.ShieldGenerators).Max = 1
} }
if(certifications.contains(FortificationEngineering)) { if (certifications.contains(FortificationEngineering)) {
counts(DeployedItem.boomer).Max = 25 counts(DeployedItem.boomer).Max = 25
counts(DeployedItem.he_mine).Max = 25 counts(DeployedItem.he_mine).Max = 25
counts(DeployedItem.spitfire_turret).Max = 15 counts(DeployedItem.spitfire_turret).Max = 15
@ -506,8 +533,7 @@ object DeployableToolbox {
categories(DeployableCategory.SmallTurrets).Max = 15 categories(DeployableCategory.SmallTurrets).Max = 15
categories(DeployableCategory.Sensors).Max = 25 categories(DeployableCategory.Sensors).Max = 25
categories(DeployableCategory.TankTraps).Max = 5 categories(DeployableCategory.TankTraps).Max = 5
} } else {
else {
counts(DeployedItem.boomer).Max = 20 counts(DeployedItem.boomer).Max = 20
counts(DeployedItem.he_mine).Max = 20 counts(DeployedItem.he_mine).Max = 20
counts(DeployedItem.spitfire_turret).Max = 10 counts(DeployedItem.spitfire_turret).Max = 10
@ -518,11 +544,11 @@ object DeployableToolbox {
categories(DeployableCategory.Sensors).Max = 20 categories(DeployableCategory.Sensors).Max = 20
} }
if(certifications.contains(AdvancedHacking)) { if (certifications.contains(AdvancedHacking)) {
counts(DeployedItem.sensor_shield).Max = 20 counts(DeployedItem.sensor_shield).Max = 20
} }
} }
if(certifications.contains(CertificationType.GroundSupport)) { if (certifications.contains(CertificationType.GroundSupport)) {
counts(DeployedItem.router_telepad_deployable).Max = 1024 counts(DeployedItem.router_telepad_deployable).Max = 1024
categories(DeployableCategory.Telepads).Max = 1024 categories(DeployableCategory.Telepads).Max = 1024
} }
@ -535,12 +561,17 @@ object DeployableToolbox {
* @param certification the new certification * @param certification the new certification
* @param certificationSet the group of previous certifications being tracked * @param certificationSet the group of previous certifications being tracked
*/ */
def AddToDeployableQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = { def AddToDeployableQuantities(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
import CertificationType._ import CertificationType._
if(certificationSet contains certification) { if (certificationSet contains certification) {
certification match { certification match {
case AdvancedHacking => case AdvancedHacking =>
if(certificationSet contains CombatEngineering) { if (certificationSet contains CombatEngineering) {
counts(DeployedItem.sensor_shield).Max = 20 counts(DeployedItem.sensor_shield).Max = 20
} }
@ -553,7 +584,7 @@ object DeployableToolbox {
categories(DeployableCategory.Mines).Max = 20 categories(DeployableCategory.Mines).Max = 20
categories(DeployableCategory.SmallTurrets).Max = 10 categories(DeployableCategory.SmallTurrets).Max = 10
categories(DeployableCategory.Sensors).Max = 20 categories(DeployableCategory.Sensors).Max = 20
if(certificationSet contains AdvancedHacking) { if (certificationSet contains AdvancedHacking) {
counts(DeployedItem.sensor_shield).Max = 20 counts(DeployedItem.sensor_shield).Max = 20
} }
@ -582,11 +613,21 @@ object DeployableToolbox {
categories(DeployableCategory.TankTraps).Max = 5 categories(DeployableCategory.TankTraps).Max = 5
case AdvancedEngineering => case AdvancedEngineering =>
if(!certificationSet.contains(AssaultEngineering)) { if (!certificationSet.contains(AssaultEngineering)) {
AddToDeployableQuantities(counts, categories, AssaultEngineering, certificationSet ++ Set(AssaultEngineering)) AddToDeployableQuantities(
counts,
categories,
AssaultEngineering,
certificationSet ++ Set(AssaultEngineering)
)
} }
if(!certificationSet.contains(FortificationEngineering)) { if (!certificationSet.contains(FortificationEngineering)) {
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering)) AddToDeployableQuantities(
counts,
categories,
FortificationEngineering,
certificationSet ++ Set(FortificationEngineering)
)
} }
// case GroundSupport => // case GroundSupport =>
@ -605,9 +646,14 @@ object DeployableToolbox {
* @param certification the new certification * @param certification the new certification
* @param certificationSet the group of previous certifications being tracked * @param certificationSet the group of previous certifications being tracked
*/ */
def RemoveFromDeployablesQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = { def RemoveFromDeployablesQuantities(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
import CertificationType._ import CertificationType._
if(!certificationSet.contains(certification)) { if (!certificationSet.contains(certification)) {
certification match { certification match {
case AdvancedHacking => case AdvancedHacking =>
counts(DeployedItem.sensor_shield).Max = 0 counts(DeployedItem.sensor_shield).Max = 0
@ -630,12 +676,12 @@ object DeployableToolbox {
//counts(DeployedItem.portable_manned_turret_tr).Max = 0 //counts(DeployedItem.portable_manned_turret_tr).Max = 0
//counts(DeployedItem.portable_manned_turret_vs).Max = 0 //counts(DeployedItem.portable_manned_turret_vs).Max = 0
counts(DeployedItem.deployable_shield_generator).Max = 0 counts(DeployedItem.deployable_shield_generator).Max = 0
categories(DeployableCategory.Sensors).Max = if(certificationSet contains CombatEngineering) 20 else 0 categories(DeployableCategory.Sensors).Max = if (certificationSet contains CombatEngineering) 20 else 0
categories(DeployableCategory.FieldTurrets).Max = 0 categories(DeployableCategory.FieldTurrets).Max = 0
categories(DeployableCategory.ShieldGenerators).Max = 0 categories(DeployableCategory.ShieldGenerators).Max = 0
case FortificationEngineering => case FortificationEngineering =>
val ce : Int = if(certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0 val ce: Int = if (certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0
counts(DeployedItem.boomer).Max = ce * 20 counts(DeployedItem.boomer).Max = ce * 20
counts(DeployedItem.he_mine).Max = ce * 20 counts(DeployedItem.he_mine).Max = ce * 20
counts(DeployedItem.spitfire_turret).Max = ce * 10 counts(DeployedItem.spitfire_turret).Max = ce * 10
@ -650,10 +696,10 @@ object DeployableToolbox {
categories(DeployableCategory.TankTraps).Max = 0 categories(DeployableCategory.TankTraps).Max = 0
case AdvancedEngineering => case AdvancedEngineering =>
if(!certificationSet.contains(AssaultEngineering)) { if (!certificationSet.contains(AssaultEngineering)) {
RemoveFromDeployablesQuantities(counts, categories, AssaultEngineering, certificationSet) RemoveFromDeployablesQuantities(counts, categories, AssaultEngineering, certificationSet)
} }
if(!certificationSet.contains(FortificationEngineering)) { if (!certificationSet.contains(FortificationEngineering)) {
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet) RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
} }

View file

@ -3,12 +3,16 @@ package net.psforever.objects.avatar
object FirstTimeEvents { object FirstTimeEvents {
object TR { object TR {
val InfantryWeapons : Set[String] = Set( val InfantryWeapons: Set[String] = Set(
"used_chainblade","used_repeater","used_cycler","used_mini_chaingun","used_striker", "used_chainblade",
"used_repeater",
"used_cycler",
"used_mini_chaingun",
"used_striker",
"used_anniversary_guna" "used_anniversary_guna"
) )
val Vehicles : Set[String] = Set( val Vehicles: Set[String] = Set(
"used_heavy_grenade_launcher", "used_heavy_grenade_launcher",
"used_apc_tr_weapon", "used_apc_tr_weapon",
"used_15mm_chaingun", "used_15mm_chaingun",
@ -18,27 +22,38 @@ object FirstTimeEvents {
"used_colossus_cluster_bomb_pod", "used_colossus_cluster_bomb_pod",
"used_colossus_dual_100mm_cannons", "used_colossus_dual_100mm_cannons",
"used_colossus_tank_cannon", "used_colossus_tank_cannon",
"visited_threemanheavybuggy","visited_battlewagon","visited_apc_tr","visited_prowler", "visited_threemanheavybuggy",
"visited_colossus_flight","visited_colossus_gunner" "visited_battlewagon",
"visited_apc_tr",
"visited_prowler",
"visited_colossus_flight",
"visited_colossus_gunner"
) )
val Other : Set[String] = Set( val Other: Set[String] = Set(
"used_trhev_dualcycler","used_trhev_pounder","used_trhev_burster", "used_trhev_dualcycler",
"used_colossus_dual_100mm_cannons","used_colossus_tank_cannon", "used_trhev_pounder",
"used_trhev_burster",
"used_colossus_dual_100mm_cannons",
"used_colossus_tank_cannon",
"used_energy_gun_tr", "used_energy_gun_tr",
"visited_portable_manned_turret_tr" "visited_portable_manned_turret_tr"
) )
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
} }
object NC { object NC {
val InfantryWeapons : Set[String] = Set( val InfantryWeapons: Set[String] = Set(
"used_magcutter","used_isp","used_gauss","used_r_shotgun","used_hunterseeker", "used_magcutter",
"used_isp",
"used_gauss",
"used_r_shotgun",
"used_hunterseeker",
"used_anniversary_gun" "used_anniversary_gun"
) )
val Vehicles : Set[String] = Set( val Vehicles: Set[String] = Set(
"used_firebird", "used_firebird",
"used_gauss_cannon", "used_gauss_cannon",
"used_apc_nc_weapon", "used_apc_nc_weapon",
@ -48,26 +63,36 @@ object FirstTimeEvents {
"used_peregrine_mechhammer", "used_peregrine_mechhammer",
"used_peregrine_particle_cannon", "used_peregrine_particle_cannon",
"used_peregrine_sparrow", "used_peregrine_sparrow",
"visited_twomanheavybuggy","visited_thunderer","visited_apc_nc","visited_vanguard", "visited_twomanheavybuggy",
"visited_peregrine_flight","visited_peregrine_gunner" "visited_thunderer",
"visited_apc_nc",
"visited_vanguard",
"visited_peregrine_flight",
"visited_peregrine_gunner"
) )
val Other : Set[String] = Set( val Other: Set[String] = Set(
"used_nchev_scattercannon","used_nchev_falcon","used_nchev_sparrow", "used_nchev_scattercannon",
"used_nchev_falcon",
"used_nchev_sparrow",
"used_energy_gun_nc", "used_energy_gun_nc",
"visited_portable_manned_turret_nc" "visited_portable_manned_turret_nc"
) )
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
} }
object VS { object VS {
val InfantryWeapons : Set[String] = Set( val InfantryWeapons: Set[String] = Set(
"used_forceblade","used_beamer","used_pulsar","used_lasher","used_lancer", "used_forceblade",
"used_beamer",
"used_pulsar",
"used_lasher",
"used_lancer",
"used_anniversary_gunb" "used_anniversary_gunb"
) )
val Vehicles : Set[String] = Set( val Vehicles: Set[String] = Set(
"used_fluxpod", "used_fluxpod",
"used_apc_vs_weapon", "used_apc_vs_weapon",
"used_heavy_rail_beam", "used_heavy_rail_beam",
@ -78,27 +103,45 @@ object FirstTimeEvents {
"used_aphelion_immolation_cannon", "used_aphelion_immolation_cannon",
"used_aphelion_plasma_rocket_pod", "used_aphelion_plasma_rocket_pod",
"used_aphelion_ppa", "used_aphelion_ppa",
"visited_twomanhoverbuggy","visited_aurora","visited_apc_vs","visited_magrider", "visited_twomanhoverbuggy",
"visited_aphelion_flight","visited_aphelion_gunner" "visited_aurora",
"visited_apc_vs",
"visited_magrider",
"visited_aphelion_flight",
"visited_aphelion_gunner"
) )
val Other : Set[String] = Set( val Other: Set[String] = Set(
"used_vshev_quasar","used_vshev_comet","used_vshev_starfire", "used_vshev_quasar",
"used_vshev_comet",
"used_vshev_starfire",
"used_energy_gun_vs", "used_energy_gun_vs",
"visited_portable_manned_turret_vs" "visited_portable_manned_turret_vs"
) )
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
} }
object Standard { object Standard {
val InfantryWeapons : Set[String] = Set( val InfantryWeapons: Set[String] = Set(
"used_grenade_plasma","used_grenade_jammer","used_grenade_frag", "used_grenade_plasma",
"used_grenade_jammer",
"used_grenade_frag",
"used_katana", "used_katana",
"used_ilc9","used_suppressor","used_punisher","used_flechette","used_phoenix","used_thumper","used_rocklet","used_bolt_driver","used_heavy_sniper","used_oicw","used_flamethrower" "used_ilc9",
"used_suppressor",
"used_punisher",
"used_flechette",
"used_phoenix",
"used_thumper",
"used_rocklet",
"used_bolt_driver",
"used_heavy_sniper",
"used_oicw",
"used_flamethrower"
) )
val Vehicles : Set[String] = Set( val Vehicles: Set[String] = Set(
"used_armor_siphon", "used_armor_siphon",
"used_ntu_siphon", "used_ntu_siphon",
"used_ballgun", "used_ballgun",
@ -116,50 +159,95 @@ object FirstTimeEvents {
"used_vulture_nose_cannon", "used_vulture_nose_cannon",
"used_vulture_tail_cannon", "used_vulture_tail_cannon",
"used_liberator_bombardier", "used_liberator_bombardier",
"visited_ams","visited_ant", "visited_ams",
"visited_quadassault","visited_fury","visited_quadstealth", "visited_ant",
"visited_two_man_assault_buggy","visited_skyguard", "visited_quadassault",
"visited_mediumtransport","visited_apc","visited_lightning", "visited_fury",
"visited_mosquito","visited_lightgunship","visited_wasp", "visited_quadstealth",
"visited_liberator","visited_vulture","visited_dropship","visited_galaxy_gunship", "visited_two_man_assault_buggy",
"visited_phantasm","visited_lodestar" "visited_skyguard",
"visited_mediumtransport",
"visited_apc",
"visited_lightning",
"visited_mosquito",
"visited_lightgunship",
"visited_wasp",
"visited_liberator",
"visited_vulture",
"visited_dropship",
"visited_galaxy_gunship",
"visited_phantasm",
"visited_lodestar"
) )
val Facilities : Set[String] = Set( val Facilities: Set[String] = Set(
"visited_broadcast_warpgate","visited_warpgate_small", "visited_broadcast_warpgate",
"visited_respawn_terminal","visited_deconstruction_terminal", "visited_warpgate_small",
"visited_capture_terminal","visited_secondary_capture","visited_LLU_socket","visited_resource_silo", "visited_respawn_terminal",
"visited_med_terminal","visited_adv_med_terminal","visited_repair_silo", "visited_deconstruction_terminal",
"visited_order_terminal","visited_certification_terminal","visited_implant_terminal","visited_locker", "visited_capture_terminal",
"visited_ground_vehicle_terminal","visited_bfr_terminal","visited_air_vehicle_terminal","visited_galaxy_terminal", "visited_secondary_capture",
"visited_generator","visited_generator_terminal", "visited_LLU_socket",
"visited_wall_turret","used_phalanx","used_phalanx_avcombo","used_phalanx_flakcombo", "visited_resource_silo",
"visited_med_terminal",
"visited_adv_med_terminal",
"visited_repair_silo",
"visited_order_terminal",
"visited_certification_terminal",
"visited_implant_terminal",
"visited_locker",
"visited_ground_vehicle_terminal",
"visited_bfr_terminal",
"visited_air_vehicle_terminal",
"visited_galaxy_terminal",
"visited_generator",
"visited_generator_terminal",
"visited_wall_turret",
"used_phalanx",
"used_phalanx_avcombo",
"used_phalanx_flakcombo",
"visited_external_door_lock" "visited_external_door_lock"
) )
val Other : Set[String] = Set( val Other: Set[String] = Set(
"used_command_uplink", "used_command_uplink",
"used_med_app","used_nano_dispenser","used_bank","used_ace","used_advanced_ace","used_rek","used_trek","used_laze_pointer","used_telepad", "used_med_app",
"visited_motion_sensor","visited_sensor_shield", "used_nano_dispenser",
"visited_spitfire_turret","visited_spitfire_cloaked","visited_spitfire_aa", "used_bank",
"visited_shield_generator","visited_tank_traps" "used_ace",
"used_advanced_ace",
"used_rek",
"used_trek",
"used_laze_pointer",
"used_telepad",
"visited_motion_sensor",
"visited_sensor_shield",
"visited_spitfire_turret",
"visited_spitfire_cloaked",
"visited_spitfire_aa",
"visited_shield_generator",
"visited_tank_traps"
) )
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
} }
object Cavern { object Cavern {
val InfantryWeapons : Set[String] = Set( val InfantryWeapons: Set[String] = Set(
"used_spiker","used_radiator","used_maelstrom" "used_spiker",
"used_radiator",
"used_maelstrom"
) )
val Vehicles : Set[String] = Set( val Vehicles: Set[String] = Set(
"used_scythe", "used_scythe",
"used_flail_weapon", "used_flail_weapon",
"visited_switchblade","visited_flail","visited_router" "visited_switchblade",
"visited_flail",
"visited_router"
) )
val Facilities : Set[String] = Set( val Facilities: Set[String] = Set(
"used_ancient_turret_weapon", "used_ancient_turret_weapon",
"visited_vanu_control_console", "visited_vanu_control_console",
"visited_ancient_air_vehicle_terminal", "visited_ancient_air_vehicle_terminal",
@ -172,21 +260,43 @@ object FirstTimeEvents {
"visited_energy_crystal" "visited_energy_crystal"
) )
val Other : Set[String] = Set( val Other: Set[String] = Set(
"visited_vanu_module" "visited_vanu_module"
) )
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
} }
val Maps : Set[String] = Set( val Maps: Set[String] = Set(
"map01","map02","map03","map04","map05","map06","map07","map08","map09","map10", "map01",
"map11","map12","map13","map14","map15","map16", "map02",
"ugd01","ugd02","ugd03","ugd04","ugd05","ugd06", "map03",
"map96","map97","map98","map99" "map04",
"map05",
"map06",
"map07",
"map08",
"map09",
"map10",
"map11",
"map12",
"map13",
"map14",
"map15",
"map16",
"ugd01",
"ugd02",
"ugd03",
"ugd04",
"ugd05",
"ugd06",
"map96",
"map97",
"map98",
"map99"
) )
val Monoliths : Set[String] = Set( val Monoliths: Set[String] = Set(
"visited_monolith_amerish", "visited_monolith_amerish",
"visited_monolith_ceryshen", "visited_monolith_ceryshen",
"visited_monolith_cyssor", "visited_monolith_cyssor",
@ -198,7 +308,7 @@ object FirstTimeEvents {
"visited_monolith_solsar" "visited_monolith_solsar"
) )
val Gingerman : Set[String] = Set( val Gingerman: Set[String] = Set(
"visited_gingerman_atar", "visited_gingerman_atar",
"visited_gingerman_dahaka", "visited_gingerman_dahaka",
"visited_gingerman_hvar", "visited_gingerman_hvar",
@ -211,7 +321,7 @@ object FirstTimeEvents {
"visited_gingerman_zal" "visited_gingerman_zal"
) )
val Sled : Set[String] = Set( val Sled: Set[String] = Set(
"visited_sled01", "visited_sled01",
"visited_sled02", "visited_sled02",
"visited_sled04", "visited_sled04",
@ -222,7 +332,7 @@ object FirstTimeEvents {
"visited_sled09" "visited_sled09"
) )
val Snowman : Set[String] = Set( val Snowman: Set[String] = Set(
"visited_snowman_amerish", "visited_snowman_amerish",
"visited_snowman_ceryshen", "visited_snowman_ceryshen",
"visited_snowman_cyssor", "visited_snowman_cyssor",
@ -234,7 +344,7 @@ object FirstTimeEvents {
"visited_snowman_solsar" "visited_snowman_solsar"
) )
val Charlie : Set[String] = Set( val Charlie: Set[String] = Set(
"visited_charlie01", "visited_charlie01",
"visited_charlie02", "visited_charlie02",
"visited_charlie03", "visited_charlie03",
@ -246,22 +356,58 @@ object FirstTimeEvents {
"visited_charlie09" "visited_charlie09"
) )
val BattleRanks : Set[String] = Set( val BattleRanks: Set[String] = Set(
"xpe_battle_rank_1","xpe_battle_rank_2","xpe_battle_rank_3","xpe_battle_rank_4","xpe_battle_rank_5", "xpe_battle_rank_1",
"xpe_battle_rank_6","xpe_battle_rank_7","xpe_battle_rank_8","xpe_battle_rank_9","xpe_battle_rank_10", "xpe_battle_rank_2",
"xpe_battle_rank_11","xpe_battle_rank_12","xpe_battle_rank_13","xpe_battle_rank_14","xpe_battle_rank_15", "xpe_battle_rank_3",
"xpe_battle_rank_16","xpe_battle_rank_17","xpe_battle_rank_18","xpe_battle_rank_19","xpe_battle_rank_20", "xpe_battle_rank_4",
"xpe_battle_rank_21","xpe_battle_rank_22","xpe_battle_rank_23","xpe_battle_rank_24","xpe_battle_rank_25", "xpe_battle_rank_5",
"xpe_battle_rank_26","xpe_battle_rank_27","xpe_battle_rank_28","xpe_battle_rank_29","xpe_battle_rank_30", "xpe_battle_rank_6",
"xpe_battle_rank_31","xpe_battle_rank_32","xpe_battle_rank_33","xpe_battle_rank_34","xpe_battle_rank_35", "xpe_battle_rank_7",
"xpe_battle_rank_36","xpe_battle_rank_37","xpe_battle_rank_38","xpe_battle_rank_39","xpe_battle_rank_40" "xpe_battle_rank_8",
"xpe_battle_rank_9",
"xpe_battle_rank_10",
"xpe_battle_rank_11",
"xpe_battle_rank_12",
"xpe_battle_rank_13",
"xpe_battle_rank_14",
"xpe_battle_rank_15",
"xpe_battle_rank_16",
"xpe_battle_rank_17",
"xpe_battle_rank_18",
"xpe_battle_rank_19",
"xpe_battle_rank_20",
"xpe_battle_rank_21",
"xpe_battle_rank_22",
"xpe_battle_rank_23",
"xpe_battle_rank_24",
"xpe_battle_rank_25",
"xpe_battle_rank_26",
"xpe_battle_rank_27",
"xpe_battle_rank_28",
"xpe_battle_rank_29",
"xpe_battle_rank_30",
"xpe_battle_rank_31",
"xpe_battle_rank_32",
"xpe_battle_rank_33",
"xpe_battle_rank_34",
"xpe_battle_rank_35",
"xpe_battle_rank_36",
"xpe_battle_rank_37",
"xpe_battle_rank_38",
"xpe_battle_rank_39",
"xpe_battle_rank_40"
) )
val CommandRanks : Set[String] = Set( val CommandRanks: Set[String] = Set(
"xpe_command_rank_1","xpe_command_rank_2","xpe_command_rank_3","xpe_command_rank_4","xpe_command_rank_5" "xpe_command_rank_1",
"xpe_command_rank_2",
"xpe_command_rank_3",
"xpe_command_rank_4",
"xpe_command_rank_5"
) )
val Training : Set[String] = Set( val Training: Set[String] = Set(
"training_welcome", "training_welcome",
"training_map", "training_map",
"training_hart", "training_hart",
@ -275,13 +421,13 @@ object FirstTimeEvents {
"training_implants" "training_implants"
) )
val OldTraining : Set[String] = Set( val OldTraining: Set[String] = Set(
"training_start_tr", "training_start_tr",
"training_start_nc", "training_start_nc",
"training_start_vs" "training_start_vs"
) )
val Generic : Set[String] = Set( val Generic: Set[String] = Set(
"xpe_overhead_map", "xpe_overhead_map",
"xpe_mail_alert", "xpe_mail_alert",
"xpe_join_platoon", "xpe_join_platoon",

View file

@ -2,14 +2,13 @@
package net.psforever.objects.avatar package net.psforever.objects.avatar
import net.psforever.objects.loadouts.Loadout import net.psforever.objects.loadouts.Loadout
import net.psforever.types.LoadoutType
import scala.util.Success import scala.util.Success
class LoadoutManager(size : Int) { class LoadoutManager(size: Int) {
private val entries : Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None) private val entries: Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None)
def SaveLoadout(owner : Any, label : String, line : Int) : Unit = { def SaveLoadout(owner: Any, label: String, line: Int): Unit = {
Loadout.Create(owner, label) match { Loadout.Create(owner, label) match {
case Success(loadout) if entries.length > line => case Success(loadout) if entries.length > line =>
entries(line) = Some(loadout) entries(line) = Some(loadout)
@ -17,13 +16,14 @@ class LoadoutManager(size : Int) {
} }
} }
def LoadLoadout(line : Int) : Option[Loadout] = entries.lift(line).flatten def LoadLoadout(line: Int): Option[Loadout] = entries.lift(line).flatten
def DeleteLoadout(line : Int) : Unit = { def DeleteLoadout(line: Int): Unit = {
if(entries.length > line) { if (entries.length > line) {
entries(line) = None entries(line) = None
} }
} }
def Loadouts : Seq[(Int, Loadout)] = entries.zipWithIndex.collect { case(Some(loadout), index) => (index, loadout) } toSeq def Loadouts: Seq[(Int, Loadout)] =
entries.zipWithIndex.collect { case (Some(loadout), index) => (index, loadout) } toSeq
} }

View file

@ -7,16 +7,18 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
import net.psforever.objects.vital.resistance.ResistanceProfile import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition, final case class ComplexDeployableSource(
faction : PlanetSideEmpire.Value, obj_def: ObjectDefinition with BaseDeployableDefinition,
health : Int, faction: PlanetSideEmpire.Value,
shields : Int, health: Int,
ownerName : String, shields: Int,
position : Vector3, ownerName: String,
orientation : Vector3) extends SourceEntry { position: Vector3,
orientation: Vector3
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name) override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction override def Faction = faction
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health def Health = health
def Shields = shields def Shields = shields
def OwnerName = ownerName def OwnerName = ownerName
@ -27,7 +29,7 @@ final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDep
} }
object ComplexDeployableSource { object ComplexDeployableSource {
def apply(obj : ComplexDeployable) : ComplexDeployableSource = { def apply(obj: ComplexDeployable): ComplexDeployableSource = {
ComplexDeployableSource( ComplexDeployableSource(
obj.Definition, obj.Definition,
obj.Faction, obj.Faction,
@ -39,7 +41,7 @@ object ComplexDeployableSource {
) )
} }
def apply(obj : TurretDeployable) : ComplexDeployableSource = { def apply(obj: TurretDeployable): ComplexDeployableSource = {
ComplexDeployableSource( ComplexDeployableSource(
obj.Definition, obj.Definition,
obj.Faction, obj.Faction,

View file

@ -7,15 +7,17 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
import net.psforever.objects.vital.resistance.ResistanceProfile import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition, final case class DeployableSource(
faction : PlanetSideEmpire.Value, obj_def: ObjectDefinition with BaseDeployableDefinition,
health : Int, faction: PlanetSideEmpire.Value,
ownerName : String, health: Int,
position : Vector3, ownerName: String,
orientation : Vector3) extends SourceEntry { position: Vector3,
orientation: Vector3
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name) override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction override def Faction = faction
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health def Health = health
def OwnerName = ownerName def OwnerName = ownerName
def Position = position def Position = position
@ -25,7 +27,7 @@ final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployable
} }
object DeployableSource { object DeployableSource {
def apply(obj : PlanetSideGameObject with Deployable) : DeployableSource = { def apply(obj: PlanetSideGameObject with Deployable): DeployableSource = {
DeployableSource( DeployableSource(
obj.Definition, obj.Definition,
obj.Faction, obj.Faction,

View file

@ -6,22 +6,24 @@ import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.vital.resistance.ResistanceProfileMutators import net.psforever.objects.vital.resistance.ResistanceProfileMutators
import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class ObjectSource(obj : PlanetSideGameObject with FactionAffinity, final case class ObjectSource(
faction : PlanetSideEmpire.Value, obj: PlanetSideGameObject with FactionAffinity,
position : Vector3, faction: PlanetSideEmpire.Value,
orientation : Vector3, position: Vector3,
velocity : Option[Vector3]) extends SourceEntry { orientation: Vector3,
velocity: Option[Vector3]
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj.Definition.Name) override def Name = SourceEntry.NameFormat(obj.Definition.Name)
override def Faction = faction override def Faction = faction
def Definition = obj.Definition def Definition = obj.Definition
def Position = position def Position = position
def Orientation = orientation def Orientation = orientation
def Velocity = velocity def Velocity = velocity
def Modifiers = new ResistanceProfileMutators { } def Modifiers = new ResistanceProfileMutators {}
} }
object ObjectSource { object ObjectSource {
def apply(obj : PlanetSideGameObject with FactionAffinity) : ObjectSource = { def apply(obj: PlanetSideGameObject with FactionAffinity): ObjectSource = {
ObjectSource( ObjectSource(
obj, obj,
obj.Faction, obj.Faction,

View file

@ -6,18 +6,20 @@ import net.psforever.objects.definition.{ExoSuitDefinition, ObjectDefinition}
import net.psforever.objects.vital.resistance.ResistanceProfile import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3} import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3}
final case class PlayerSource(name : String, final case class PlayerSource(
char_id : Long, name: String,
obj_def : ObjectDefinition, char_id: Long,
faction : PlanetSideEmpire.Value, obj_def: ObjectDefinition,
exosuit : ExoSuitType.Value, faction: PlanetSideEmpire.Value,
seated : Boolean, exosuit: ExoSuitType.Value,
health : Int, seated: Boolean,
armor : Int, health: Int,
position : Vector3, armor: Int,
orientation : Vector3, position: Vector3,
velocity : Option[Vector3], orientation: Vector3,
modifiers : ResistanceProfile) extends SourceEntry { velocity: Option[Vector3],
modifiers: ResistanceProfile
) extends SourceEntry {
override def Name = name override def Name = name
override def Faction = faction override def Faction = faction
override def CharId = char_id override def CharId = char_id
@ -33,9 +35,20 @@ final case class PlayerSource(name : String,
} }
object PlayerSource { object PlayerSource {
def apply(tplayer : Player) : PlayerSource = { def apply(tplayer: Player): PlayerSource = {
PlayerSource(tplayer.Name, tplayer.CharId, tplayer.Definition, tplayer.Faction, tplayer.ExoSuit, tplayer.VehicleSeated.nonEmpty, PlayerSource(
tplayer.Health, tplayer.Armor, tplayer.Position, tplayer.Orientation, tplayer.Velocity, tplayer.Name,
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction)) tplayer.CharId,
tplayer.Definition,
tplayer.Faction,
tplayer.ExoSuit,
tplayer.VehicleSeated.nonEmpty,
tplayer.Health,
tplayer.Armor,
tplayer.Position,
tplayer.Orientation,
tplayer.Velocity,
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction)
)
} }
} }

View file

@ -28,51 +28,57 @@ import net.psforever.types.Vector3
* @param fire_time when the weapon discharged was recorded; * @param fire_time when the weapon discharged was recorded;
* defaults to `System.nanoTime` * defaults to `System.nanoTime`
*/ */
final case class Projectile(profile : ProjectileDefinition, final case class Projectile(
tool_def : ToolDefinition, profile: ProjectileDefinition,
fire_mode : FireModeDefinition, tool_def: ToolDefinition,
owner : SourceEntry, fire_mode: FireModeDefinition,
attribute_to : Int, owner: SourceEntry,
shot_origin : Vector3, attribute_to: Int,
shot_angle : Vector3, shot_origin: Vector3,
fire_time: Long = System.nanoTime) extends PlanetSideGameObject { shot_angle: Vector3,
fire_time: Long = System.nanoTime
) extends PlanetSideGameObject {
Position = shot_origin Position = shot_origin
Orientation = shot_angle Orientation = shot_angle
Velocity = { Velocity = {
val initVel : Int = profile.InitialVelocity //initial velocity val initVel: Int = profile.InitialVelocity //initial velocity
val radAngle : Double = math.toRadians(shot_angle.y) //angle of elevation val radAngle: Double = math.toRadians(shot_angle.y) //angle of elevation
val rise : Float = initVel * math.sin(radAngle).toFloat //z val rise: Float = initVel * math.sin(radAngle).toFloat //z
val ground : Float = initVel * math.cos(radAngle).toFloat //base val ground: Float = initVel * math.cos(radAngle).toFloat //base
Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise) Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise)
} }
/** Information about the current world coordinates and orientation of the projectile */ /** Information about the current world coordinates and orientation of the projectile */
val current : SimpleWorldEntity = new SimpleWorldEntity() val current: SimpleWorldEntity = new SimpleWorldEntity()
private var resolved : ProjectileResolution.Value = ProjectileResolution.Unresolved private var resolved: ProjectileResolution.Value = ProjectileResolution.Unresolved
/** /**
* Mark the projectile as being "encountered" or "managed" at least once. * Mark the projectile as being "encountered" or "managed" at least once.
*/ */
def Resolve() : Unit = { def Resolve(): Unit = {
resolved = ProjectileResolution.Resolved resolved = ProjectileResolution.Resolved
} }
def Miss() : Unit = { def Miss(): Unit = {
resolved = ProjectileResolution.MissedShot resolved = ProjectileResolution.MissedShot
} }
def isResolved : Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot def isResolved: Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot
def isMiss : Boolean = resolved == ProjectileResolution.MissedShot def isMiss: Boolean = resolved == ProjectileResolution.MissedShot
def Definition = profile def Definition = profile
} }
object Projectile { object Projectile {
/** the first projectile GUID used by all clients internally */ /** the first projectile GUID used by all clients internally */
final val BaseUID : Int = 40100 final val BaseUID: Int = 40100
/** all clients progress through 40100 to 40124 normally, skipping only for long-lived projectiles /** all clients progress through 40100 to 40124 normally, skipping only for long-lived projectiles
* 40125 to 40149 are being reserved as a guard against undetected overflow */ * 40125 to 40149 are being reserved as a guard against undetected overflow
final val RangeUID : Int = 40150 */
final val RangeUID: Int = 40150
/** /**
* Overloaded constructor for an `Unresolved` projectile. * Overloaded constructor for an `Unresolved` projectile.
@ -84,7 +90,14 @@ object Projectile {
* @param shot_angle in which direction the projectile was aimed when it was discharged * @param shot_angle in which direction the projectile was aimed when it was discharged
* @return the `Projectile` object * @return the `Projectile` object
*/ */
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, shot_origin : Vector3, shot_angle : Vector3) : Projectile = { def apply(
profile: ProjectileDefinition,
tool_def: ToolDefinition,
fire_mode: FireModeDefinition,
owner: PlanetSideGameObject with FactionAffinity,
shot_origin: Vector3,
shot_angle: Vector3
): Projectile = {
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle) Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle)
} }
@ -99,7 +112,15 @@ object Projectile {
* @param shot_angle in which direction the projectile was aimed when it was discharged * @param shot_angle in which direction the projectile was aimed when it was discharged
* @return the `Projectile` object * @return the `Projectile` object
*/ */
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, attribute_to : Int, shot_origin : Vector3, shot_angle : Vector3) : Projectile = { def apply(
profile: ProjectileDefinition,
tool_def: ToolDefinition,
fire_mode: FireModeDefinition,
owner: PlanetSideGameObject with FactionAffinity,
attribute_to: Int,
shot_origin: Vector3,
shot_angle: Vector3
): Projectile = {
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle) Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle)
} }
} }

View file

@ -7,8 +7,7 @@ package net.psforever.objects.ballistics
object ProjectileResolution extends Enumeration { object ProjectileResolution extends Enumeration {
type Type = Value type Type = Value
val val Unresolved, //original basic non-resolution
Unresolved, //original basic non-resolution
MissedShot, //projectile did not encounter any collision object and was despawned MissedShot, //projectile did not encounter any collision object and was despawned
Resolved, //a general "projectile encountered something" status with a more specific resolution Resolved, //a general "projectile encountered something" status with a more specific resolution
Hit, //direct hit, one target Hit, //direct hit, one target

View file

@ -15,10 +15,12 @@ import net.psforever.types.Vector3
* @param damage_model the kind of damage model to which the `target` is/was subject * @param damage_model the kind of damage model to which the `target` is/was subject
* @param hit_pos where the projectile hit * @param hit_pos where the projectile hit
*/ */
final case class ResolvedProjectile(resolution : ProjectileResolution.Value, final case class ResolvedProjectile(
projectile : Projectile, resolution: ProjectileResolution.Value,
target : SourceEntry, projectile: Projectile,
damage_model : DamageResistanceModel, target: SourceEntry,
hit_pos : Vector3) { damage_model: DamageResistanceModel,
val hit_time : Long = System.nanoTime hit_pos: Vector3
) {
val hit_time: Long = System.nanoTime
} }

View file

@ -10,14 +10,14 @@ import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.types.{PlanetSideEmpire, Vector3}
trait SourceEntry extends WorldEntity { trait SourceEntry extends WorldEntity {
def Name : String = "" def Name: String = ""
def Definition : ObjectDefinition def Definition: ObjectDefinition
def CharId : Long = 0L def CharId: Long = 0L
def Faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL def Faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
def Position_=(pos : Vector3) = Position def Position_=(pos: Vector3) = Position
def Orientation_=(pos : Vector3) = Position def Orientation_=(pos: Vector3) = Position
def Velocity_=(pos : Option[Vector3]) = Velocity def Velocity_=(pos: Option[Vector3]) = Velocity
def Modifiers : ResistanceProfile def Modifiers: ResistanceProfile
} }
object SourceEntry { object SourceEntry {
@ -29,18 +29,19 @@ object SourceEntry {
def Modifiers = null def Modifiers = null
} }
def apply(target : PlanetSideGameObject with FactionAffinity) : SourceEntry = { def apply(target: PlanetSideGameObject with FactionAffinity): SourceEntry = {
target match { target match {
case obj : Player => PlayerSource(obj) case obj: Player => PlayerSource(obj)
case obj : Vehicle => VehicleSource(obj) case obj: Vehicle => VehicleSource(obj)
case obj : ComplexDeployable => ComplexDeployableSource(obj) case obj: ComplexDeployable => ComplexDeployableSource(obj)
case obj : SimpleDeployable => DeployableSource(obj) case obj: SimpleDeployable => DeployableSource(obj)
case _ => ObjectSource(target) case _ => ObjectSource(target)
} }
} }
def NameFormat(name : String) : String = { def NameFormat(name: String): String = {
name.replace("_", " ") name
.replace("_", " ")
.split(" ") .split(" ")
.map(_.capitalize) .map(_.capitalize)
.mkString(" ") .mkString(" ")

View file

@ -6,17 +6,19 @@ import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.vital.resistance.ResistanceProfile import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3} import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class VehicleSource(obj_def : VehicleDefinition, final case class VehicleSource(
faction : PlanetSideEmpire.Value, obj_def: VehicleDefinition,
health : Int, faction: PlanetSideEmpire.Value,
shields : Int, health: Int,
position : Vector3, shields: Int,
orientation : Vector3, position: Vector3,
velocity : Option[Vector3], orientation: Vector3,
modifiers : ResistanceProfile) extends SourceEntry { velocity: Option[Vector3],
modifiers: ResistanceProfile
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name) override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction override def Faction = faction
def Definition : VehicleDefinition = obj_def def Definition: VehicleDefinition = obj_def
def Health = health def Health = health
def Shields = shields def Shields = shields
def Position = position def Position = position
@ -26,7 +28,7 @@ final case class VehicleSource(obj_def : VehicleDefinition,
} }
object VehicleSource { object VehicleSource {
def apply(obj : Vehicle) : VehicleSource = { def apply(obj: Vehicle): VehicleSource = {
VehicleSource( VehicleSource(
obj.Definition, obj.Definition,
obj.Faction, obj.Faction,

View file

@ -4,19 +4,18 @@ package net.psforever.objects.ce
import net.psforever.objects.definition.ComplexDeployableDefinition import net.psforever.objects.definition.ComplexDeployableDefinition
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
abstract class ComplexDeployable(cdef : ComplexDeployableDefinition) extends PlanetSideServerObject abstract class ComplexDeployable(cdef: ComplexDeployableDefinition) extends PlanetSideServerObject with Deployable {
with Deployable { private var shields: Int = 0
private var shields : Int = 0
def Shields : Int = shields def Shields: Int = shields
def Shields_=(toShields : Int) : Int = { def Shields_=(toShields: Int): Int = {
shields = math.min(math.max(0, toShields), MaxShields) shields = math.min(math.max(0, toShields), MaxShields)
Shields Shields
} }
def MaxShields : Int = { def MaxShields: Int = {
0//Definition.MaxShields 0 //Definition.MaxShields
} }
def Definition = cdef def Definition = cdef

View file

@ -9,41 +9,38 @@ import net.psforever.objects.zones.ZoneAware
import net.psforever.packet.game.DeployableIcon import net.psforever.packet.game.DeployableIcon
import net.psforever.types.PlanetSideEmpire import net.psforever.types.PlanetSideEmpire
trait Deployable extends FactionAffinity trait Deployable extends FactionAffinity with Vitality with OwnableByPlayer with ZoneAware {
with Vitality this: PlanetSideGameObject =>
with OwnableByPlayer private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
with ZoneAware {
this : PlanetSideGameObject =>
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
def MaxHealth : Int def MaxHealth: Int
def Faction : PlanetSideEmpire.Value = faction def Faction: PlanetSideEmpire.Value = faction
override def Faction_=(toFaction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = { override def Faction_=(toFaction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
faction = toFaction faction = toFaction
Faction Faction
} }
def DamageModel : DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel] def DamageModel: DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
def Definition : DeployableDefinition def Definition: DeployableDefinition
} }
object Deployable { object Deployable {
object Category { object Category {
def Of(item : DeployedItem.Value) : DeployableCategory.Value = deployablesToCategories(item) def Of(item: DeployedItem.Value): DeployableCategory.Value = deployablesToCategories(item)
def Includes(category : DeployableCategory.Value) : List[DeployedItem.Value] = { def Includes(category: DeployableCategory.Value): List[DeployedItem.Value] = {
(for { (for {
(ce, cat) <- deployablesToCategories (ce, cat) <- deployablesToCategories
if cat == category if cat == category
} yield ce) toList } yield ce) toList
} }
def OfAll() : Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories def OfAll(): Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories
private val deployablesToCategories : Map[DeployedItem.Value, DeployableCategory.Value] = Map( private val deployablesToCategories: Map[DeployedItem.Value, DeployableCategory.Value] = Map(
DeployedItem.boomer -> DeployableCategory.Boomers, DeployedItem.boomer -> DeployableCategory.Boomers,
DeployedItem.he_mine -> DeployableCategory.Mines, DeployedItem.he_mine -> DeployableCategory.Mines,
DeployedItem.jammer_mine -> DeployableCategory.Mines, DeployedItem.jammer_mine -> DeployableCategory.Mines,
@ -63,9 +60,9 @@ object Deployable {
} }
object Icon { object Icon {
def apply(item : DeployedItem.Value) : DeployableIcon.Value = ceicon(item.id) def apply(item: DeployedItem.Value): DeployableIcon.Value = ceicon(item.id)
private val ceicon : Map[Int, DeployableIcon.Value] = Map( private val ceicon: Map[Int, DeployableIcon.Value] = Map(
DeployedItem.boomer.id -> DeployableIcon.Boomer, DeployedItem.boomer.id -> DeployableIcon.Boomer,
DeployedItem.he_mine.id -> DeployableIcon.HEMine, DeployedItem.he_mine.id -> DeployableIcon.HEMine,
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine, DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
@ -85,7 +82,7 @@ object Deployable {
} }
object UI { object UI {
def apply(item : DeployedItem.Value) : (Int, Int) = planetsideAttribute(item) def apply(item: DeployedItem.Value): (Int, Int) = planetsideAttribute(item)
/** /**
* The attribute values to be invoked in `PlanetsideAttributeMessage` packets * The attribute values to be invoked in `PlanetsideAttributeMessage` packets
@ -93,7 +90,7 @@ object Deployable {
* The first number is for the actual count field. * The first number is for the actual count field.
* The second number is for the maximum count field. * The second number is for the maximum count field.
*/ */
private val planetsideAttribute : Map[DeployedItem.Value, (Int, Int)] = Map( private val planetsideAttribute: Map[DeployedItem.Value, (Int, Int)] = Map(
DeployedItem.boomer -> (94, 83), DeployedItem.boomer -> (94, 83),
DeployedItem.he_mine -> (95, 84), DeployedItem.he_mine -> (95, 84),
DeployedItem.jammer_mine -> (96, 85), DeployedItem.jammer_mine -> (96, 85),
@ -108,6 +105,6 @@ object Deployable {
DeployedItem.portable_manned_turret_tr -> (103, 92), DeployedItem.portable_manned_turret_tr -> (103, 92),
DeployedItem.portable_manned_turret_vs -> (103, 92), DeployedItem.portable_manned_turret_vs -> (103, 92),
DeployedItem.sensor_shield -> (104, 93) DeployedItem.sensor_shield -> (104, 93)
).withDefaultValue((0,0)) ).withDefaultValue((0, 0))
} }
} }

View file

@ -4,14 +4,5 @@ package net.psforever.objects.ce
object DeployableCategory extends Enumeration { object DeployableCategory extends Enumeration {
type Type = Value type Type = Value
val val Boomers, Mines, SmallTurrets, Sensors, TankTraps, FieldTurrets, ShieldGenerators, Telepads = Value
Boomers,
Mines,
SmallTurrets,
Sensors,
TankTraps,
FieldTurrets,
ShieldGenerators,
Telepads
= Value
} }

View file

@ -4,8 +4,7 @@ package net.psforever.objects.ce
import net.psforever.objects.PlanetSideGameObject import net.psforever.objects.PlanetSideGameObject
import net.psforever.objects.definition.SimpleDeployableDefinition import net.psforever.objects.definition.SimpleDeployableDefinition
abstract class SimpleDeployable(cdef : SimpleDeployableDefinition) extends PlanetSideGameObject abstract class SimpleDeployable(cdef: SimpleDeployableDefinition) extends PlanetSideGameObject with Deployable {
with Deployable {
Health = Definition.MaxHealth Health = Definition.MaxHealth
def Definition = cdef def Definition = cdef

View file

@ -10,37 +10,37 @@ import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
trait TelepadLike { trait TelepadLike {
private var router : Option[PlanetSideGUID] = None private var router: Option[PlanetSideGUID] = None
private var activated : Boolean = false private var activated: Boolean = false
def Router : Option[PlanetSideGUID] = router def Router: Option[PlanetSideGUID] = router
def Router_=(rguid : PlanetSideGUID) : Option[PlanetSideGUID] = Router_=(Some(rguid)) def Router_=(rguid: PlanetSideGUID): Option[PlanetSideGUID] = Router_=(Some(rguid))
def Router_=(rguid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = { def Router_=(rguid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
router match { router match {
case None => case None =>
router = rguid router = rguid
case Some(_) => case Some(_) =>
if(rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) { if (rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
router = None router = None
} }
} }
Router Router
} }
def Active : Boolean = activated def Active: Boolean = activated
def Active_=(state : Boolean) : Boolean = { def Active_=(state: Boolean): Boolean = {
activated = state activated = state
Active Active
} }
} }
object TelepadLike { object TelepadLike {
final case class Activate(obj : PlanetSideGameObject with TelepadLike) final case class Activate(obj: PlanetSideGameObject with TelepadLike)
final case class Deactivate(obj : PlanetSideGameObject with TelepadLike) final case class Deactivate(obj: PlanetSideGameObject with TelepadLike)
/** /**
* Assemble some logic for a provided object. * Assemble some logic for a provided object.
@ -48,10 +48,10 @@ object TelepadLike {
* anticipating a `Terminal` object using this same definition * anticipating a `Terminal` object using this same definition
* @param context hook to the local `Actor` system * @param context hook to the local `Actor` system
*/ */
def Setup(obj : Amenity, context : ActorContext) : Unit = { def Setup(obj: Amenity, context: ActorContext): Unit = {
obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID
import akka.actor.Props import akka.actor.Props
if(obj.Actor == Default.Actor) { if (obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[TelepadControl], obj), PlanetSideServerObject.UniqueActorName(obj)) obj.Actor = context.actorOf(Props(classOf[TelepadControl], obj), PlanetSideServerObject.UniqueActorName(obj))
} }
} }
@ -64,20 +64,19 @@ object TelepadLike {
* @param zone where the router is located * @param zone where the router is located
* @return the pair of units that compose the teleportation system * @return the pair of units that compose the teleportation system
*/ */
def AppraiseTeleportationSystem(router : Vehicle, zone : Zone) : Option[(Utility.InternalTelepad, TelepadDeployable)] = { def AppraiseTeleportationSystem(router: Vehicle, zone: Zone): Option[(Utility.InternalTelepad, TelepadDeployable)] = {
import net.psforever.objects.vehicles.UtilityType import net.psforever.objects.vehicles.UtilityType
import net.psforever.types.DriveState import net.psforever.types.DriveState
router.Utility(UtilityType.internal_router_telepad_deployable) match { router.Utility(UtilityType.internal_router_telepad_deployable) match {
//if the vehicle has an internal telepad, it is allowed to be a Router (that's a weird way of saying it) //if the vehicle has an internal telepad, it is allowed to be a Router (that's a weird way of saying it)
case Some(util : Utility.InternalTelepad) => case Some(util: Utility.InternalTelepad) =>
//check for a readied remote telepad //check for a readied remote telepad
zone.GUID(util.Telepad) match { zone.GUID(util.Telepad) match {
case Some(telepad : TelepadDeployable) => case Some(telepad: TelepadDeployable) =>
//determine whether to activate both the Router's internal telepad and the deployed remote telepad //determine whether to activate both the Router's internal telepad and the deployed remote telepad
if(router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) { if (router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
Some((util, telepad)) Some((util, telepad))
} } else {
else {
None None
} }
case _ => case _ =>
@ -96,8 +95,8 @@ object TelepadLike {
* a placeholder like this is easy to reason around. * a placeholder like this is easy to reason around.
* @param obj an entity that extends `TelepadLike` * @param obj an entity that extends `TelepadLike`
*/ */
class TelepadControl(obj : TelepadLike) extends akka.actor.Actor { class TelepadControl(obj: TelepadLike) extends akka.actor.Actor {
def receive : akka.actor.Actor.Receive = { def receive: akka.actor.Actor.Receive = {
case _ => ; case _ => ;
} }
} }

View file

@ -4,19 +4,19 @@ package net.psforever.objects.definition
import net.psforever.objects.definition.converter.AmmoBoxConverter import net.psforever.objects.definition.converter.AmmoBoxConverter
import net.psforever.objects.equipment.Ammo import net.psforever.objects.equipment.Ammo
class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) { class AmmoBoxDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize import net.psforever.objects.equipment.EquipmentSize
private val ammoType : Ammo.Value = Ammo(objectId) //let throw NoSuchElementException private val ammoType: Ammo.Value = Ammo(objectId) //let throw NoSuchElementException
private var capacity : Int = 1 private var capacity: Int = 1
Name = "ammo box" Name = "ammo box"
Size = EquipmentSize.Inventory Size = EquipmentSize.Inventory
Packet = AmmoBoxDefinition.converter Packet = AmmoBoxDefinition.converter
def AmmoType : Ammo.Value = ammoType def AmmoType: Ammo.Value = ammoType
def Capacity : Int = capacity def Capacity: Int = capacity
def Capacity_=(capacity : Int) : Int = { def Capacity_=(capacity: Int): Int = {
this.capacity = capacity this.capacity = capacity
Capacity Capacity
} }
@ -25,11 +25,11 @@ class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object AmmoBoxDefinition { object AmmoBoxDefinition {
private val converter = new AmmoBoxConverter() private val converter = new AmmoBoxConverter()
def apply(objectId: Int) : AmmoBoxDefinition = { def apply(objectId: Int): AmmoBoxDefinition = {
new AmmoBoxDefinition(objectId) new AmmoBoxDefinition(objectId)
} }
def apply(ammoType : Ammo.Value) : AmmoBoxDefinition = { def apply(ammoType: Ammo.Value): AmmoBoxDefinition = {
new AmmoBoxDefinition(ammoType.id) new AmmoBoxDefinition(ammoType.id)
} }
} }

View file

@ -9,8 +9,7 @@ import net.psforever.objects.vital.VitalityDefinition
* The definition for game objects that look like other people, and also for players. * The definition for game objects that look like other people, and also for players.
* @param objectId the object's identifier number * @param objectId the object's identifier number
*/ */
class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId) class AvatarDefinition(objectId: Int) extends ObjectDefinition(objectId) with VitalityDefinition {
with VitalityDefinition {
Avatars(objectId) //let throw NoSuchElementException Avatars(objectId) //let throw NoSuchElementException
Packet = AvatarDefinition.converter Packet = AvatarDefinition.converter
} }
@ -18,11 +17,11 @@ class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId)
object AvatarDefinition { object AvatarDefinition {
private val converter = new AvatarConverter() private val converter = new AvatarConverter()
def apply(objectId: Int) : AvatarDefinition = { def apply(objectId: Int): AvatarDefinition = {
new AvatarDefinition(objectId) new AvatarDefinition(objectId)
} }
def apply(avatar : Avatars.Value) : AvatarDefinition = { def apply(avatar: Avatars.Value): AvatarDefinition = {
new AvatarDefinition(avatar.id) new AvatarDefinition(avatar.id)
} }
} }

View file

@ -2,21 +2,21 @@
package net.psforever.objects.definition package net.psforever.objects.definition
abstract class BasicDefinition { abstract class BasicDefinition {
private var name : String = "definition" private var name: String = "definition"
private var descriptor : Option[String] = None private var descriptor: Option[String] = None
def Name : String = name def Name: String = name
def Name_=(name : String) : String = { def Name_=(name: String): String = {
this.name = name this.name = name
Name Name
} }
def Descriptor : String = descriptor.getOrElse(Name) def Descriptor: String = descriptor.getOrElse(Name)
def Descriptor_=(description : String) : String = Descriptor_=(Some(description)) def Descriptor_=(description: String): String = Descriptor_=(Some(description))
def Descriptor_=(description : Option[String]) : String = { def Descriptor_=(description: Option[String]): String = {
descriptor = description descriptor = description
Descriptor Descriptor
} }

View file

@ -7,26 +7,28 @@ import net.psforever.objects.vehicles.CargoVehicleRestriction
* The definition for a cargo hold. * The definition for a cargo hold.
*/ */
class CargoDefinition extends BasicDefinition { class CargoDefinition extends BasicDefinition {
/** a restriction on the type of exo-suit a person can wear */ /** a restriction on the type of exo-suit a person can wear */
private var vehicleRestriction : CargoVehicleRestriction.Value = CargoVehicleRestriction.Small private var vehicleRestriction: CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
/** the user can escape while the vehicle is moving */ /** the user can escape while the vehicle is moving */
private var bailable : Boolean = true private var bailable: Boolean = true
Name = "cargo" Name = "cargo"
def CargoRestriction : CargoVehicleRestriction.Value = { def CargoRestriction: CargoVehicleRestriction.Value = {
this.vehicleRestriction this.vehicleRestriction
} }
def CargoRestriction_=(restriction : CargoVehicleRestriction.Value) : CargoVehicleRestriction.Value = { def CargoRestriction_=(restriction: CargoVehicleRestriction.Value): CargoVehicleRestriction.Value = {
this.vehicleRestriction = restriction this.vehicleRestriction = restriction
restriction restriction
} }
def Bailable : Boolean = { def Bailable: Boolean = {
this.bailable this.bailable
} }
def Bailable_=(canBail : Boolean) : Boolean = { def Bailable_=(canBail: Boolean): Boolean = {
this.bailable = canBail this.bailable = canBail
canBail canBail
} }

View file

@ -8,39 +8,39 @@ import net.psforever.types.CertificationType
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
class ConstructionItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) { class ConstructionItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
CItem(objectId) //let throw NoSuchElementException CItem(objectId) //let throw NoSuchElementException
private val modes : ListBuffer[ConstructionFireMode] = ListBuffer() private val modes: ListBuffer[ConstructionFireMode] = ListBuffer()
Packet = new ACEConverter Packet = new ACEConverter
def Modes : ListBuffer[ConstructionFireMode] = modes def Modes: ListBuffer[ConstructionFireMode] = modes
} }
object ConstructionItemDefinition { object ConstructionItemDefinition {
def apply(objectId : Int) : ConstructionItemDefinition = { def apply(objectId: Int): ConstructionItemDefinition = {
new ConstructionItemDefinition(objectId) new ConstructionItemDefinition(objectId)
} }
def apply(cItem : CItem.Value) : ConstructionItemDefinition = { def apply(cItem: CItem.Value): ConstructionItemDefinition = {
new ConstructionItemDefinition(cItem.id) new ConstructionItemDefinition(cItem.id)
} }
} }
class ConstructionFireMode { class ConstructionFireMode {
private val deployables : ListBuffer[DeployedItem.Value] = ListBuffer.empty private val deployables: ListBuffer[DeployedItem.Value] = ListBuffer.empty
private val permissions : ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty private val permissions: ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty
def Permissions : ListBuffer[Set[CertificationType.Value]] = permissions def Permissions: ListBuffer[Set[CertificationType.Value]] = permissions
def Deployables : ListBuffer[DeployedItem.Value] = deployables def Deployables: ListBuffer[DeployedItem.Value] = deployables
def Item(deployable : DeployedItem.Value) : ListBuffer[DeployedItem.Value] = { def Item(deployable: DeployedItem.Value): ListBuffer[DeployedItem.Value] = {
deployables += deployable deployables += deployable
permissions += Set.empty[CertificationType.Value] permissions += Set.empty[CertificationType.Value]
deployables deployables
} }
def Item(deployPair : (DeployedItem.Value, Set[CertificationType.Value])) : ListBuffer[DeployedItem.Value] = { def Item(deployPair: (DeployedItem.Value, Set[CertificationType.Value])): ListBuffer[DeployedItem.Value] = {
val (deployable, permission) = deployPair val (deployable, permission) = deployPair
deployables += deployable deployables += deployable
permissions += permission permissions += permission

View file

@ -8,31 +8,34 @@ import net.psforever.objects.inventory.InventoryTile
* The definition for any piece of `Equipment`. * The definition for any piece of `Equipment`.
* @param objectId the object's identifier number * @param objectId the object's identifier number
*/ */
abstract class EquipmentDefinition(objectId : Int) extends ObjectDefinition(objectId) { abstract class EquipmentDefinition(objectId: Int) extends ObjectDefinition(objectId) {
/** the size of the item when placed in an EquipmentSlot / holster / mounting */ /** the size of the item when placed in an EquipmentSlot / holster / mounting */
private var size : EquipmentSize.Value = EquipmentSize.Blocked private var size: EquipmentSize.Value = EquipmentSize.Blocked
/** the size of the item when placed in the grid inventory space */ /** the size of the item when placed in the grid inventory space */
private var tile : InventoryTile = InventoryTile.Tile11 private var tile: InventoryTile = InventoryTile.Tile11
/** a correction for the z-coordinate for some dropped items to avoid sinking into the ground */ /** a correction for the z-coordinate for some dropped items to avoid sinking into the ground */
private var dropOffset : Float = 0f private var dropOffset: Float = 0f
def Size : EquipmentSize.Value = size def Size: EquipmentSize.Value = size
def Size_=(newSize : EquipmentSize.Value) : EquipmentSize.Value = { def Size_=(newSize: EquipmentSize.Value): EquipmentSize.Value = {
size = newSize size = newSize
Size Size
} }
def Tile : InventoryTile = tile def Tile: InventoryTile = tile
def Tile_=(newTile : InventoryTile) : InventoryTile = { def Tile_=(newTile: InventoryTile): InventoryTile = {
tile = newTile tile = newTile
Tile Tile
} }
def DropOffset : Float = dropOffset def DropOffset: Float = dropOffset
def DropOffset(offset : Float) : Float = { def DropOffset(offset: Float): Float = {
dropOffset = offset dropOffset = offset
DropOffset DropOffset
} }

View file

@ -13,107 +13,107 @@ import net.psforever.types.{CertificationType, ExoSuitType, PlanetSideEmpire}
* Players are influenced by the exo-suit they wear in a variety of ways, with speed and available equipment slots being major differences. * Players are influenced by the exo-suit they wear in a variety of ways, with speed and available equipment slots being major differences.
* @param suitType the `Enumeration` corresponding to this exo-suit * @param suitType the `Enumeration` corresponding to this exo-suit
*/ */
class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicDefinition class ExoSuitDefinition(private val suitType: ExoSuitType.Value)
extends BasicDefinition
with ResistanceProfileMutators with ResistanceProfileMutators
with DamageResistanceModel { with DamageResistanceModel {
protected var permissions : List[CertificationType.Value] = List.empty protected var permissions: List[CertificationType.Value] = List.empty
protected var maxArmor : Int = 0 protected var maxArmor: Int = 0
protected val holsters : Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked) protected val holsters: Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked)
protected var inventoryScale : InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile protected var inventoryScale: InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile
protected var inventoryOffset : Int = 0 protected var inventoryOffset: Int = 0
protected var maxCapacitor : Int = 0 protected var maxCapacitor: Int = 0
protected var capacitorRechargeDelayMillis : Int = 0 protected var capacitorRechargeDelayMillis: Int = 0
protected var capacitorRechargePerSecond : Int = 0 protected var capacitorRechargePerSecond: Int = 0
protected var capacitorDrainPerSecond : Int = 0 protected var capacitorDrainPerSecond: Int = 0
Name = "exo-suit" Name = "exo-suit"
DamageUsing = StandardInfantryDamage DamageUsing = StandardInfantryDamage
ResistUsing = StandardInfantryResistance ResistUsing = StandardInfantryResistance
Model = StandardResolutions.Infantry Model = StandardResolutions.Infantry
def SuitType : ExoSuitType.Value = suitType def SuitType: ExoSuitType.Value = suitType
def MaxArmor : Int = maxArmor def MaxArmor: Int = maxArmor
def MaxArmor_=(armor : Int) : Int = { def MaxArmor_=(armor: Int): Int = {
maxArmor = math.min(math.max(0, armor), 65535) maxArmor = math.min(math.max(0, armor), 65535)
MaxArmor MaxArmor
} }
def MaxCapacitor : Int = maxCapacitor def MaxCapacitor: Int = maxCapacitor
def MaxCapacitor_=(value : Int) : Int = { def MaxCapacitor_=(value: Int): Int = {
maxCapacitor = value maxCapacitor = value
maxCapacitor maxCapacitor
} }
def CapacitorRechargeDelayMillis : Int = capacitorRechargeDelayMillis def CapacitorRechargeDelayMillis: Int = capacitorRechargeDelayMillis
def CapacitorRechargeDelayMillis_=(value : Int) : Int = { def CapacitorRechargeDelayMillis_=(value: Int): Int = {
capacitorRechargeDelayMillis = value capacitorRechargeDelayMillis = value
capacitorRechargeDelayMillis capacitorRechargeDelayMillis
} }
def CapacitorRechargePerSecond : Int = capacitorRechargePerSecond def CapacitorRechargePerSecond: Int = capacitorRechargePerSecond
def CapacitorRechargePerSecond_=(value : Int) : Int = { def CapacitorRechargePerSecond_=(value: Int): Int = {
capacitorRechargePerSecond = value capacitorRechargePerSecond = value
capacitorRechargePerSecond capacitorRechargePerSecond
} }
def CapacitorDrainPerSecond : Int = capacitorDrainPerSecond def CapacitorDrainPerSecond: Int = capacitorDrainPerSecond
def CapacitorDrainPerSecond_=(value : Int) : Int = { def CapacitorDrainPerSecond_=(value: Int): Int = {
capacitorDrainPerSecond = value capacitorDrainPerSecond = value
capacitorDrainPerSecond capacitorDrainPerSecond
} }
def InventoryScale : InventoryTile = inventoryScale def InventoryScale: InventoryTile = inventoryScale
def InventoryScale_=(scale : InventoryTile) : InventoryTile = { def InventoryScale_=(scale: InventoryTile): InventoryTile = {
inventoryScale = scale inventoryScale = scale
InventoryScale InventoryScale
} }
def InventoryOffset : Int = inventoryOffset def InventoryOffset: Int = inventoryOffset
def InventoryOffset_=(offset : Int) : Int = { def InventoryOffset_=(offset: Int): Int = {
inventoryOffset = math.min(math.max(0, offset), 65535) inventoryOffset = math.min(math.max(0, offset), 65535)
InventoryOffset InventoryOffset
} }
def Holsters : Array[EquipmentSize.Value] = holsters def Holsters: Array[EquipmentSize.Value] = holsters
def Holster(slot : Int) : EquipmentSize.Value = { def Holster(slot: Int): EquipmentSize.Value = {
if(slot >= 0 && slot < 5) { if (slot >= 0 && slot < 5) {
holsters(slot) holsters(slot)
} } else {
else {
EquipmentSize.Blocked EquipmentSize.Blocked
} }
} }
def Holster(slot : Int, value : EquipmentSize.Value) : EquipmentSize.Value = { def Holster(slot: Int, value: EquipmentSize.Value): EquipmentSize.Value = {
if(slot >= 0 && slot < 5) { if (slot >= 0 && slot < 5) {
holsters(slot) = value holsters(slot) = value
holsters(slot) holsters(slot)
} } else {
else {
EquipmentSize.Blocked EquipmentSize.Blocked
} }
} }
def Permissions : List[CertificationType.Value] = permissions def Permissions: List[CertificationType.Value] = permissions
def Permissions_=(certs : List[CertificationType.Value]) : List[CertificationType.Value] = { def Permissions_=(certs: List[CertificationType.Value]): List[CertificationType.Value] = {
permissions = certs permissions = certs
Permissions Permissions
} }
def Use : ExoSuitDefinition = this def Use: ExoSuitDefinition = this
def canEqual(other: Any): Boolean = other.isInstanceOf[ExoSuitDefinition] def canEqual(other: Any): Boolean = other.isInstanceOf[ExoSuitDefinition]
override def equals(other: Any): Boolean = other match { override def equals(other: Any): Boolean =
other match {
case that: ExoSuitDefinition => case that: ExoSuitDefinition =>
(that canEqual this) && (that canEqual this) &&
suitType == that.suitType suitType == that.suitType
@ -126,20 +126,20 @@ class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicD
} }
} }
class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends ExoSuitDefinition(suitType) { class SpecialExoSuitDefinition(private val suitType: ExoSuitType.Value) extends ExoSuitDefinition(suitType) {
Name = "heavy_armor" Name = "heavy_armor"
Descriptor = "heavy_armor" Descriptor = "heavy_armor"
private var activatedSpecial : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal private var activatedSpecial: SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = activatedSpecial def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = activatedSpecial
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = { def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
activatedSpecial = state activatedSpecial = state
UsingSpecial UsingSpecial
} }
override def Use : ExoSuitDefinition = { override def Use: ExoSuitDefinition = {
val obj = new SpecialExoSuitDefinition(SuitType) val obj = new SpecialExoSuitDefinition(SuitType)
obj.Permissions = Permissions obj.Permissions = Permissions
obj.MaxArmor = MaxArmor obj.MaxArmor = MaxArmor
@ -165,24 +165,19 @@ class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends
} }
object SpecialExoSuitDefinition { object SpecialExoSuitDefinition {
def apply(suitType : ExoSuitType.Value) : SpecialExoSuitDefinition = { def apply(suitType: ExoSuitType.Value): SpecialExoSuitDefinition = {
new SpecialExoSuitDefinition(suitType) new SpecialExoSuitDefinition(suitType)
} }
object Mode extends Enumeration { object Mode extends Enumeration {
type Type = Value type Type = Value
val val Normal, Anchored, Overdrive, Shielded = Value
Normal,
Anchored,
Overdrive,
Shielded
= Value
} }
} }
object ExoSuitDefinition { object ExoSuitDefinition {
def apply(suitType : ExoSuitType.Value) : ExoSuitDefinition = { def apply(suitType: ExoSuitType.Value): ExoSuitDefinition = {
new ExoSuitDefinition(suitType) new ExoSuitDefinition(suitType)
} }
@ -192,12 +187,13 @@ object ExoSuitDefinition {
* @param faction the faction the player belongs to for this exosuit * @param faction the faction the player belongs to for this exosuit
* @return the exo-suit definition * @return the exo-suit definition
*/ */
def Select(suit : ExoSuitType.Value, faction : PlanetSideEmpire.Value) : ExoSuitDefinition = { def Select(suit: ExoSuitType.Value, faction: PlanetSideEmpire.Value): ExoSuitDefinition = {
suit match { suit match {
case ExoSuitType.Infiltration => GlobalDefinitions.Infiltration.Use case ExoSuitType.Infiltration => GlobalDefinitions.Infiltration.Use
case ExoSuitType.Agile => GlobalDefinitions.Agile.Use case ExoSuitType.Agile => GlobalDefinitions.Agile.Use
case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use
case ExoSuitType.MAX => faction match { case ExoSuitType.MAX =>
faction match {
case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use
case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use
case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use

View file

@ -17,16 +17,20 @@ import scala.collection.mutable
* @param implantType the type of implant that is defined * @param implantType the type of implant that is defined
* @see `ImplantType` * @see `ImplantType`
*/ */
class ImplantDefinition(private val implantType : Int) extends BasicDefinition { class ImplantDefinition(private val implantType: Int) extends BasicDefinition {
ImplantType(implantType) ImplantType(implantType)
/** how long it takes the implant to become ready for activation; is milliseconds */ /** how long it takes the implant to become ready for activation; is milliseconds */
private var initializationDuration : Long = 0L private var initializationDuration: Long = 0L
/** a passive certification is activated as soon as it is ready (or other condition) */ /** a passive certification is activated as soon as it is ready (or other condition) */
private var passive : Boolean = false private var passive: Boolean = false
/** how much turning on the implant costs */ /** how much turning on the implant costs */
private var activationStaminaCost : Int = 0 private var activationStaminaCost: Int = 0
/** how much energy does this implant cost to remain activate per interval tick */ /** how much energy does this implant cost to remain activate per interval tick */
private var staminaCost : Int = 0 private var staminaCost: Int = 0
/** /**
* How often in milliseconds the stamina cost will be applied, per exo-suit type * How often in milliseconds the stamina cost will be applied, per exo-suit type
@ -37,59 +41,59 @@ class ImplantDefinition(private val implantType : Int) extends BasicDefinition {
* stamina_consumption_interval3 = Rexo * stamina_consumption_interval3 = Rexo
* stamina_consumption_interval4 = MAX? * stamina_consumption_interval4 = MAX?
*/ */
private var costIntervalDefault : Int = 0 private var costIntervalDefault: Int = 0
private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault) private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault)
Name = "implant" Name = "implant"
def InitializationDuration : Long = initializationDuration def InitializationDuration: Long = initializationDuration
def InitializationDuration_=(time : Long) : Long = { def InitializationDuration_=(time: Long): Long = {
initializationDuration = math.max(0, time) initializationDuration = math.max(0, time)
InitializationDuration InitializationDuration
} }
def Passive : Boolean = passive def Passive: Boolean = passive
def Passive_=(isPassive : Boolean) : Boolean = { def Passive_=(isPassive: Boolean): Boolean = {
passive = isPassive passive = isPassive
Passive Passive
} }
def ActivationStaminaCost : Int = activationStaminaCost def ActivationStaminaCost: Int = activationStaminaCost
def ActivationStaminaCost_=(charge : Int) : Int = { def ActivationStaminaCost_=(charge: Int): Int = {
activationStaminaCost = math.max(0, charge) activationStaminaCost = math.max(0, charge)
ActivationStaminaCost ActivationStaminaCost
} }
def StaminaCost : Int = staminaCost def StaminaCost: Int = staminaCost
def StaminaCost_=(charge : Int) : Int = { def StaminaCost_=(charge: Int): Int = {
staminaCost = math.max(0, charge) staminaCost = math.max(0, charge)
StaminaCost StaminaCost
} }
def CostIntervalDefault: Int = {
def CostIntervalDefault : Int = {
costIntervalDefault costIntervalDefault
} }
def CostIntervalDefault_=(interval : Int) : Int = { def CostIntervalDefault_=(interval: Int): Int = {
costIntervalDefault = interval costIntervalDefault = interval
CostIntervalDefault CostIntervalDefault
} }
def GetCostIntervalByExoSuit(exosuit : ExoSuitType.Value) : Int = costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault) def GetCostIntervalByExoSuit(exosuit: ExoSuitType.Value): Int =
def CostIntervalByExoSuitHashMap : mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault)
def CostIntervalByExoSuitHashMap: mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit
def Type : ImplantType.Value = ImplantType(implantType) def Type: ImplantType.Value = ImplantType(implantType)
} }
object ImplantDefinition { object ImplantDefinition {
def apply(implantType : Int) : ImplantDefinition = { def apply(implantType: Int): ImplantDefinition = {
new ImplantDefinition(implantType) new ImplantDefinition(implantType)
} }
def apply(implantType : ImplantType.Value) : ImplantDefinition = { def apply(implantType: ImplantType.Value): ImplantDefinition = {
new ImplantDefinition(implantType.id) new ImplantDefinition(implantType.id)
} }
} }

View file

@ -8,7 +8,7 @@ import net.psforever.objects.equipment.Kits
* The definition for a personal one-time-use recovery item. * The definition for a personal one-time-use recovery item.
* @param objectId the object's identifier number * @param objectId the object's identifier number
*/ */
class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) { class KitDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize import net.psforever.objects.equipment.EquipmentSize
import net.psforever.objects.inventory.InventoryTile import net.psforever.objects.inventory.InventoryTile
Kits(objectId) //let throw NoSuchElementException Kits(objectId) //let throw NoSuchElementException
@ -21,11 +21,11 @@ class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object KitDefinition { object KitDefinition {
private val converter = new KitConverter() private val converter = new KitConverter()
def apply(objectId: Int) : KitDefinition = { def apply(objectId: Int): KitDefinition = {
new KitDefinition(objectId) new KitDefinition(objectId)
} }
def apply(kit : Kits.Value) : KitDefinition = { def apply(kit: Kits.Value): KitDefinition = {
new KitDefinition(kit.id) new KitDefinition(kit.id)
} }
} }

View file

@ -17,26 +17,28 @@ import net.psforever.objects.definition.converter.{ObjectCreateConverter, Packet
* So long as it is an `ObjectCreatePacket`, those methods can be called correctly for a game object of the desired type. * So long as it is an `ObjectCreatePacket`, those methods can be called correctly for a game object of the desired type.
* @param objectId the object's identifier number * @param objectId the object's identifier number
*/ */
abstract class ObjectDefinition(private val objectId : Int) extends BasicDefinition { abstract class ObjectDefinition(private val objectId: Int) extends BasicDefinition {
/** a data converter for this type of object */ /** a data converter for this type of object */
protected var packet : PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() { } protected var packet: PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() {}
Name = "object definition" Name = "object definition"
/** /**
* Get the conversion object. * Get the conversion object.
* @return * @return
*/ */
final def Packet : ObjectCreateConverter[PlanetSideGameObject] = packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]] final def Packet: ObjectCreateConverter[PlanetSideGameObject] =
packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]]
/** /**
* Assign this definition a conversion object. * Assign this definition a conversion object.
* @param pkt the new converter * @param pkt the new converter
* @return the current converter, after assignment * @return the current converter, after assignment
*/ */
final def Packet_=(pkt : ObjectCreateConverter[_]) : PacketConverter = { final def Packet_=(pkt: ObjectCreateConverter[_]): PacketConverter = {
packet = pkt packet = pkt
Packet Packet
} }
def ObjectId : Int = objectId def ObjectId: Int = objectId
} }

View file

@ -10,167 +10,169 @@ import net.psforever.objects.vital.{DamageType, StandardDamageProfile}
* `Tool` objects emit `ProjectileDefinition` objects and that is later wrapped into a `Projectile` object. * `Tool` objects emit `ProjectileDefinition` objects and that is later wrapped into a `Projectile` object.
* @param objectId the object's identifier number * @param objectId the object's identifier number
*/ */
class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId) class ProjectileDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with JammingUnit with JammingUnit
with StandardDamageProfile { with StandardDamageProfile {
private val projectileType : Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException private val projectileType: Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
private var acceleration : Int = 0 private var acceleration: Int = 0
private var accelerationUntil : Float = 0f private var accelerationUntil: Float = 0f
private var damageType : DamageType.Value = DamageType.None private var damageType: DamageType.Value = DamageType.None
private var damageTypeSecondary : DamageType.Value = DamageType.None private var damageTypeSecondary: DamageType.Value = DamageType.None
private var degradeDelay : Float = 1f private var degradeDelay: Float = 1f
private var degradeMultiplier : Float = 1f private var degradeMultiplier: Float = 1f
private var initialVelocity : Int = 1 private var initialVelocity: Int = 1
private var lifespan : Float = 1f private var lifespan: Float = 1f
private var damageAtEdge : Float = 1f private var damageAtEdge: Float = 1f
private var damageRadius : Float = 1f private var damageRadius: Float = 1f
private var useDamage1Subtract : Boolean = false private var useDamage1Subtract: Boolean = false
private var existsOnRemoteClients : Boolean = false //`true` spawns a server-managed object private var existsOnRemoteClients: Boolean = false //`true` spawns a server-managed object
private var remoteClientData : (Int, Int) = (0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined) private var remoteClientData: (Int, Int) =
private var autoLock : Boolean = false (0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
private var additionalEffect : Boolean = false private var autoLock: Boolean = false
private var jammerProjectile : Boolean = false private var additionalEffect: Boolean = false
private var jammerProjectile: Boolean = false
//derived calculations //derived calculations
private var distanceMax : Float = 0f private var distanceMax: Float = 0f
private var distanceFromAcceleration : Float = 0f private var distanceFromAcceleration: Float = 0f
private var distanceNoDegrade : Float = 0f private var distanceNoDegrade: Float = 0f
private var finalVelocity : Float = 0f private var finalVelocity: Float = 0f
Name = "projectile" Name = "projectile"
def ProjectileType : Projectiles.Value = projectileType def ProjectileType: Projectiles.Value = projectileType
def UseDamage1Subtract : Boolean = useDamage1Subtract def UseDamage1Subtract: Boolean = useDamage1Subtract
def UseDamage1Subtract_=(useDamage1Subtract : Boolean) : Boolean = { def UseDamage1Subtract_=(useDamage1Subtract: Boolean): Boolean = {
this.useDamage1Subtract = useDamage1Subtract this.useDamage1Subtract = useDamage1Subtract
UseDamage1Subtract UseDamage1Subtract
} }
def Acceleration : Int = acceleration def Acceleration: Int = acceleration
def Acceleration_=(accel : Int) : Int = { def Acceleration_=(accel: Int): Int = {
acceleration = accel acceleration = accel
Acceleration Acceleration
} }
def AccelerationUntil : Float = accelerationUntil def AccelerationUntil: Float = accelerationUntil
def AccelerationUntil_=(accelUntil : Float) : Float = { def AccelerationUntil_=(accelUntil: Float): Float = {
accelerationUntil = accelUntil accelerationUntil = accelUntil
AccelerationUntil AccelerationUntil
} }
def ProjectileDamageType : DamageType.Value = damageType def ProjectileDamageType: DamageType.Value = damageType
def ProjectileDamageType_=(damageType1 : DamageType.Value) : DamageType.Value = { def ProjectileDamageType_=(damageType1: DamageType.Value): DamageType.Value = {
damageType = damageType1 damageType = damageType1
ProjectileDamageType ProjectileDamageType
} }
def ProjectileDamageTypeSecondary : DamageType.Value = damageTypeSecondary def ProjectileDamageTypeSecondary: DamageType.Value = damageTypeSecondary
def ProjectileDamageTypeSecondary_=(damageTypeSecondary1 : DamageType.Value) : DamageType.Value = { def ProjectileDamageTypeSecondary_=(damageTypeSecondary1: DamageType.Value): DamageType.Value = {
damageTypeSecondary = damageTypeSecondary1 damageTypeSecondary = damageTypeSecondary1
ProjectileDamageTypeSecondary ProjectileDamageTypeSecondary
} }
def DegradeDelay : Float = degradeDelay def DegradeDelay: Float = degradeDelay
def DegradeDelay_=(degradeDelay : Float) : Float = { def DegradeDelay_=(degradeDelay: Float): Float = {
this.degradeDelay = degradeDelay this.degradeDelay = degradeDelay
DegradeDelay DegradeDelay
} }
def DegradeMultiplier : Float = degradeMultiplier def DegradeMultiplier: Float = degradeMultiplier
def DegradeMultiplier_=(degradeMultiplier : Float) : Float = { def DegradeMultiplier_=(degradeMultiplier: Float): Float = {
this.degradeMultiplier = degradeMultiplier this.degradeMultiplier = degradeMultiplier
DegradeMultiplier DegradeMultiplier
} }
def InitialVelocity : Int = initialVelocity def InitialVelocity: Int = initialVelocity
def InitialVelocity_=(initialVelocity : Int) : Int = { def InitialVelocity_=(initialVelocity: Int): Int = {
this.initialVelocity = initialVelocity this.initialVelocity = initialVelocity
InitialVelocity InitialVelocity
} }
def Lifespan : Float = lifespan def Lifespan: Float = lifespan
def Lifespan_=(lifespan : Float) : Float = { def Lifespan_=(lifespan: Float): Float = {
this.lifespan = lifespan this.lifespan = lifespan
Lifespan Lifespan
} }
def DamageAtEdge : Float = damageAtEdge def DamageAtEdge: Float = damageAtEdge
def DamageAtEdge_=(damageAtEdge : Float) : Float = { def DamageAtEdge_=(damageAtEdge: Float): Float = {
this.damageAtEdge = damageAtEdge this.damageAtEdge = damageAtEdge
DamageAtEdge DamageAtEdge
} }
def DamageRadius : Float = damageRadius def DamageRadius: Float = damageRadius
def DamageRadius_=(damageRadius : Float) : Float = { def DamageRadius_=(damageRadius: Float): Float = {
this.damageRadius = damageRadius this.damageRadius = damageRadius
DamageRadius DamageRadius
} }
def ExistsOnRemoteClients : Boolean = existsOnRemoteClients def ExistsOnRemoteClients: Boolean = existsOnRemoteClients
def ExistsOnRemoteClients_=(existsOnRemoteClients : Boolean) : Boolean = { def ExistsOnRemoteClients_=(existsOnRemoteClients: Boolean): Boolean = {
this.existsOnRemoteClients = existsOnRemoteClients this.existsOnRemoteClients = existsOnRemoteClients
ExistsOnRemoteClients ExistsOnRemoteClients
} }
def RemoteClientData : (Int, Int) = remoteClientData def RemoteClientData: (Int, Int) = remoteClientData
def RemoteClientData_=(remoteClientData : (Int, Int)) : (Int, Int) = { def RemoteClientData_=(remoteClientData: (Int, Int)): (Int, Int) = {
this.remoteClientData = remoteClientData this.remoteClientData = remoteClientData
RemoteClientData RemoteClientData
} }
def AutoLock : Boolean = autoLock def AutoLock: Boolean = autoLock
def AutoLock_=(lockState : Boolean) : Boolean = { def AutoLock_=(lockState: Boolean): Boolean = {
autoLock = lockState autoLock = lockState
AutoLock AutoLock
} }
def AdditionalEffect : Boolean = additionalEffect def AdditionalEffect: Boolean = additionalEffect
def AdditionalEffect_=(effect : Boolean) : Boolean = { def AdditionalEffect_=(effect: Boolean): Boolean = {
additionalEffect = effect additionalEffect = effect
AdditionalEffect AdditionalEffect
} }
def JammerProjectile : Boolean = jammerProjectile def JammerProjectile: Boolean = jammerProjectile
def JammerProjectile_=(effect : Boolean) : Boolean = { def JammerProjectile_=(effect: Boolean): Boolean = {
jammerProjectile = effect jammerProjectile = effect
JammerProjectile JammerProjectile
} }
def DistanceMax : Float = distanceMax //accessor only def DistanceMax: Float = distanceMax //accessor only
def DistanceFromAcceleration : Float = distanceFromAcceleration //accessor only def DistanceFromAcceleration: Float = distanceFromAcceleration //accessor only
def DistanceNoDegrade : Float = distanceNoDegrade //accessor only def DistanceNoDegrade: Float = distanceNoDegrade //accessor only
def FinalVelocity : Float = finalVelocity //accessor only def FinalVelocity: Float = finalVelocity //accessor only
} }
object ProjectileDefinition { object ProjectileDefinition {
def apply(projectileType : Projectiles.Value) : ProjectileDefinition = { def apply(projectileType: Projectiles.Value): ProjectileDefinition = {
new ProjectileDefinition(projectileType.id) new ProjectileDefinition(projectileType.id)
} }
def CalculateDerivedFields(pdef : ProjectileDefinition) : Unit = { def CalculateDerivedFields(pdef: ProjectileDefinition): Unit = {
val (distanceMax, distanceFromAcceleration, finalVelocity) : (Float, Float, Float) = if(pdef.Acceleration == 0) { val (distanceMax, distanceFromAcceleration, finalVelocity): (Float, Float, Float) = if (pdef.Acceleration == 0) {
(pdef.InitialVelocity * pdef.Lifespan, 0, pdef.InitialVelocity.toFloat) (pdef.InitialVelocity * pdef.Lifespan, 0, pdef.InitialVelocity.toFloat)
} } else {
else { val distanceFromAcceleration =
val distanceFromAcceleration = (pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil) (pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil)
val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil
val distanceAfterAcceleration = finalVelocity * (pdef.Lifespan - pdef.AccelerationUntil) val distanceAfterAcceleration = finalVelocity * (pdef.Lifespan - pdef.AccelerationUntil)
(distanceFromAcceleration + distanceAfterAcceleration, distanceFromAcceleration, finalVelocity) (distanceFromAcceleration + distanceAfterAcceleration, distanceFromAcceleration, finalVelocity)
@ -179,13 +181,11 @@ object ProjectileDefinition {
pdef.distanceFromAcceleration = distanceFromAcceleration pdef.distanceFromAcceleration = distanceFromAcceleration
pdef.finalVelocity = finalVelocity pdef.finalVelocity = finalVelocity
pdef.distanceNoDegrade = if(pdef.DegradeDelay == 0f) { pdef.distanceNoDegrade = if (pdef.DegradeDelay == 0f) {
pdef.distanceMax pdef.distanceMax
} } else if (pdef.DegradeDelay < pdef.AccelerationUntil) {
else if(pdef.DegradeDelay < pdef.AccelerationUntil) {
(pdef.DegradeDelay * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.DegradeDelay * pdef.DegradeDelay) (pdef.DegradeDelay * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.DegradeDelay * pdef.DegradeDelay)
} } else {
else {
pdef.distanceFromAcceleration + pdef.finalVelocity * (pdef.DegradeDelay - pdef.AccelerationUntil) pdef.distanceFromAcceleration + pdef.finalVelocity * (pdef.DegradeDelay - pdef.AccelerationUntil)
} }
} }

View file

@ -7,41 +7,44 @@ import net.psforever.objects.vehicles.SeatArmorRestriction
* The definition for a seat. * The definition for a seat.
*/ */
class SeatDefinition extends BasicDefinition { class SeatDefinition extends BasicDefinition {
/** a restriction on the type of exo-suit a person can wear */ /** a restriction on the type of exo-suit a person can wear */
private var armorRestriction : SeatArmorRestriction.Value = SeatArmorRestriction.NoMax private var armorRestriction: SeatArmorRestriction.Value = SeatArmorRestriction.NoMax
/** the user can escape while the vehicle is moving */ /** the user can escape while the vehicle is moving */
private var bailable : Boolean = false private var bailable: Boolean = false
/** any controlled weapon */ /** any controlled weapon */
private var weaponMount : Option[Int] = None private var weaponMount: Option[Int] = None
Name = "seat" Name = "seat"
def ArmorRestriction : SeatArmorRestriction.Value = { def ArmorRestriction: SeatArmorRestriction.Value = {
this.armorRestriction this.armorRestriction
} }
def ArmorRestriction_=(restriction : SeatArmorRestriction.Value) : SeatArmorRestriction.Value = { def ArmorRestriction_=(restriction: SeatArmorRestriction.Value): SeatArmorRestriction.Value = {
this.armorRestriction = restriction this.armorRestriction = restriction
restriction restriction
} }
def Bailable : Boolean = { def Bailable: Boolean = {
this.bailable this.bailable
} }
def Bailable_=(canBail : Boolean) : Boolean = { def Bailable_=(canBail: Boolean): Boolean = {
this.bailable = canBail this.bailable = canBail
canBail canBail
} }
def ControlledWeapon : Option[Int] = { def ControlledWeapon: Option[Int] = {
this.weaponMount this.weaponMount
} }
def ControlledWeapon_=(wep : Int) : Option[Int] = { def ControlledWeapon_=(wep: Int): Option[Int] = {
ControlledWeapon_=(Some(wep)) ControlledWeapon_=(Some(wep))
} }
def ControlledWeapon_=(wep : Option[Int]) : Option[Int] = { def ControlledWeapon_=(wep: Option[Int]): Option[Int] = {
this.weaponMount = wep this.weaponMount = wep
ControlledWeapon ControlledWeapon
} }

View file

@ -7,42 +7,48 @@ import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
import net.psforever.objects.definition.converter.SmallDeployableConverter import net.psforever.objects.definition.converter.SmallDeployableConverter
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.vital.resistance.ResistanceProfileMutators import net.psforever.objects.vital.resistance.ResistanceProfileMutators
import net.psforever.objects.vital.{DamageResistanceModel, NoResistanceSelection, StandardDeployableDamage, VitalityDefinition} import net.psforever.objects.vital.{
DamageResistanceModel,
NoResistanceSelection,
StandardDeployableDamage,
VitalityDefinition
}
import scala.concurrent.duration._ import scala.concurrent.duration._
trait BaseDeployableDefinition { trait BaseDeployableDefinition {
private var category : DeployableCategory.Value = DeployableCategory.Boomers private var category: DeployableCategory.Value = DeployableCategory.Boomers
private var deployTime : Long = (1 second).toMillis //ms private var deployTime: Long = (1 second).toMillis //ms
def Item : DeployedItem.Value def Item: DeployedItem.Value
def DeployCategory : DeployableCategory.Value = category def DeployCategory: DeployableCategory.Value = category
def DeployCategory_=(cat : DeployableCategory.Value) : DeployableCategory.Value = { def DeployCategory_=(cat: DeployableCategory.Value): DeployableCategory.Value = {
category = cat category = cat
DeployCategory DeployCategory
} }
def DeployTime : Long = deployTime def DeployTime: Long = deployTime
def DeployTime_=(time : FiniteDuration) : Long = DeployTime_=(time.toMillis) def DeployTime_=(time: FiniteDuration): Long = DeployTime_=(time.toMillis)
def DeployTime_=(time: Long) : Long = { def DeployTime_=(time: Long): Long = {
deployTime = time deployTime = time
DeployTime DeployTime
} }
def Initialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { } def Initialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { } def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
def Uninitialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { } def Uninitialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { } def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
} }
abstract class DeployableDefinition(objectId : Int) extends ObjectDefinition(objectId) abstract class DeployableDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with DamageResistanceModel with DamageResistanceModel
with ResistanceProfileMutators with ResistanceProfileMutators
with VitalityDefinition with VitalityDefinition
@ -51,22 +57,22 @@ abstract class DeployableDefinition(objectId : Int) extends ObjectDefinition(obj
DamageUsing = StandardDeployableDamage DamageUsing = StandardDeployableDamage
ResistUsing = NoResistanceSelection ResistUsing = NoResistanceSelection
def Item : DeployedItem.Value = item def Item: DeployedItem.Value = item
} }
class SimpleDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId) { class SimpleDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId) {
Packet = new SmallDeployableConverter Packet = new SmallDeployableConverter
} }
abstract class ComplexDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId) abstract class ComplexDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId)
object SimpleDeployableDefinition { object SimpleDeployableDefinition {
def apply(item : DeployedItem.Value) : SimpleDeployableDefinition = def apply(item: DeployedItem.Value): SimpleDeployableDefinition =
new SimpleDeployableDefinition(item.id) new SimpleDeployableDefinition(item.id)
def SimpleUninitialize(obj : PlanetSideGameObject, context : ActorContext) : Unit = { } def SimpleUninitialize(obj: PlanetSideGameObject, context: ActorContext): Unit = {}
def SimpleUninitialize(obj : PlanetSideServerObject, context : ActorContext) : Unit = { def SimpleUninitialize(obj: PlanetSideServerObject, context: ActorContext): Unit = {
context.stop(obj.Actor) context.stop(obj.Actor)
obj.Actor = Default.Actor obj.Actor = Default.Actor
} }

View file

@ -3,7 +3,7 @@ package net.psforever.objects.definition
import net.psforever.objects.equipment.SItem import net.psforever.objects.equipment.SItem
class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) { class SimpleItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize import net.psforever.objects.equipment.EquipmentSize
SItem(objectId) //let throw NoSuchElementException SItem(objectId) //let throw NoSuchElementException
Name = "tool" Name = "tool"
@ -11,11 +11,11 @@ class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId)
} }
object SimpleItemDefinition { object SimpleItemDefinition {
def apply(objectId : Int) : SimpleItemDefinition = { def apply(objectId: Int): SimpleItemDefinition = {
new SimpleItemDefinition(objectId) new SimpleItemDefinition(objectId)
} }
def apply(simpItem : SItem.Value) : SimpleItemDefinition = { def apply(simpItem: SItem.Value): SimpleItemDefinition = {
new SimpleItemDefinition(simpItem.id) new SimpleItemDefinition(simpItem.id)
} }
} }

View file

@ -6,27 +6,27 @@ import net.psforever.objects.equipment.FireModeDefinition
import scala.collection.mutable import scala.collection.mutable
class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) { class ToolDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition] private val ammoTypes: mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
private val projectileTypes : mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition] private val projectileTypes: mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition] private val fireModes: mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
private var defaultFireModeIndex : Option[Int] = None private var defaultFireModeIndex: Option[Int] = None
Name = "tool" Name = "tool"
Packet = ToolDefinition.converter Packet = ToolDefinition.converter
def AmmoTypes : mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes def AmmoTypes: mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
def ProjectileTypes : mutable.ListBuffer[ProjectileDefinition] = projectileTypes def ProjectileTypes: mutable.ListBuffer[ProjectileDefinition] = projectileTypes
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes def FireModes: mutable.ListBuffer[FireModeDefinition] = fireModes
def NextFireModeIndex(index : Int) : Int = index + 1 def NextFireModeIndex(index: Int): Int = index + 1
def DefaultFireModeIndex : Int = defaultFireModeIndex.getOrElse(0) def DefaultFireModeIndex: Int = defaultFireModeIndex.getOrElse(0)
def DefaultFireModeIndex_=(index : Int) : Int = DefaultFireModeIndex_=(Some(index)) def DefaultFireModeIndex_=(index: Int): Int = DefaultFireModeIndex_=(Some(index))
def DefaultFireModeIndex_=(index : Option[Int]) : Int = { def DefaultFireModeIndex_=(index: Option[Int]): Int = {
defaultFireModeIndex = index defaultFireModeIndex = index
DefaultFireModeIndex DefaultFireModeIndex
} }
@ -35,7 +35,7 @@ class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object ToolDefinition { object ToolDefinition {
private val converter = new ToolConverter() private val converter = new ToolConverter()
def apply(objectId : Int) : ToolDefinition = { def apply(objectId: Int): ToolDefinition = {
new ToolDefinition(objectId) new ToolDefinition(objectId)
} }
} }

View file

@ -15,37 +15,39 @@ import scala.concurrent.duration._
* An object definition system used to construct and retain the parameters of various vehicles. * An object definition system used to construct and retain the parameters of various vehicles.
* @param objectId the object id that is associated with this sort of `Vehicle` * @param objectId the object id that is associated with this sort of `Vehicle`
*/ */
class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) class VehicleDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with VitalityDefinition with VitalityDefinition
with ResistanceProfileMutators with ResistanceProfileMutators
with DamageResistanceModel { with DamageResistanceModel {
/** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */ /** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */
private var maxShields : Int = 0 private var maxShields: Int = 0
/* key - seat index, value - seat object */ /* key - seat index, value - seat object */
private val seats : mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]() private val seats: mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
private val cargo : mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]() private val cargo: mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
/* key - entry point index, value - seat index */ /* key - entry point index, value - seat index */
private val mountPoints : mutable.HashMap[Int, Int] = mutable.HashMap() private val mountPoints: mutable.HashMap[Int, Int] = mutable.HashMap()
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */ /* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
private val weapons : mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]() private val weapons: mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
private var deployment : Boolean = false private var deployment: Boolean = false
private val utilities : mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap() private val utilities: mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
private val utilityOffsets : mutable.HashMap[Int, Vector3] = mutable.HashMap() private val utilityOffsets: mutable.HashMap[Int, Vector3] = mutable.HashMap()
private var deploymentTime_Deploy : Int = 0 //ms private var deploymentTime_Deploy: Int = 0 //ms
private var deploymentTime_Undeploy : Int = 0 //ms private var deploymentTime_Undeploy: Int = 0 //ms
private var trunkSize : InventoryTile = InventoryTile.None private var trunkSize: InventoryTile = InventoryTile.None
private var trunkOffset : Int = 0 private var trunkOffset: Int = 0
/** The position offset of the trunk, orientation as East = 0 */ /** The position offset of the trunk, orientation as East = 0 */
private var trunkLocation : Vector3 = Vector3.Zero private var trunkLocation: Vector3 = Vector3.Zero
private var canCloak : Boolean = false private var canCloak: Boolean = false
private var canFly : Boolean = false private var canFly: Boolean = false
private var canBeOwned : Boolean = true private var canBeOwned: Boolean = true
private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0) private var serverVehicleOverrideSpeeds: (Int, Int) = (0, 0)
private var deconTime : Option[FiniteDuration] = None private var deconTime: Option[FiniteDuration] = None
private var maxCapacitor : Int = 0 private var maxCapacitor: Int = 0
private var maxNtuCapacitor : Int = 0 private var maxNtuCapacitor: Int = 0
private var destroyedModel : Option[DestroyedVehicle.Value] = None private var destroyedModel: Option[DestroyedVehicle.Value] = None
Name = "vehicle" Name = "vehicle"
Packet = VehicleDefinition.converter Packet = VehicleDefinition.converter
DamageUsing = StandardVehicleDamage DamageUsing = StandardVehicleDamage
@ -54,135 +56,135 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
RepairDistance = 10 RepairDistance = 10
RepairRestoresAt = 1 RepairRestoresAt = 1
def MaxShields : Int = maxShields def MaxShields: Int = maxShields
def MaxShields_=(shields : Int) : Int = { def MaxShields_=(shields: Int): Int = {
maxShields = shields maxShields = shields
MaxShields MaxShields
} }
def Seats : mutable.HashMap[Int, SeatDefinition] = seats def Seats: mutable.HashMap[Int, SeatDefinition] = seats
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo def Cargo: mutable.HashMap[Int, CargoDefinition] = cargo
def MountPoints : mutable.HashMap[Int, Int] = mountPoints def MountPoints: mutable.HashMap[Int, Int] = mountPoints
def CanBeOwned : Boolean = canBeOwned def CanBeOwned: Boolean = canBeOwned
def CanBeOwned_=(ownable : Boolean) : Boolean = { def CanBeOwned_=(ownable: Boolean): Boolean = {
canBeOwned = ownable canBeOwned = ownable
CanBeOwned CanBeOwned
} }
def CanCloak : Boolean = canCloak def CanCloak: Boolean = canCloak
def CanCloak_=(cloakable : Boolean) : Boolean = { def CanCloak_=(cloakable: Boolean): Boolean = {
canCloak = cloakable canCloak = cloakable
CanCloak CanCloak
} }
def CanFly : Boolean = canFly def CanFly: Boolean = canFly
def CanFly_=(flying : Boolean) : Boolean = { def CanFly_=(flying: Boolean): Boolean = {
canFly = flying canFly = flying
CanFly CanFly
} }
def Weapons : mutable.HashMap[Int, ToolDefinition] = weapons def Weapons: mutable.HashMap[Int, ToolDefinition] = weapons
def Deployment : Boolean = deployment def Deployment: Boolean = deployment
def Deployment_=(deployable : Boolean) : Boolean = { def Deployment_=(deployable: Boolean): Boolean = {
deployment = deployable deployment = deployable
Deployment Deployment
} }
def Utilities : mutable.HashMap[Int, UtilityType.Value] = utilities def Utilities: mutable.HashMap[Int, UtilityType.Value] = utilities
def UtilityOffset : mutable.HashMap[Int, Vector3] = utilityOffsets def UtilityOffset: mutable.HashMap[Int, Vector3] = utilityOffsets
def DeployTime : Int = deploymentTime_Deploy def DeployTime: Int = deploymentTime_Deploy
def DeployTime_=(dtime : Int) : Int = { def DeployTime_=(dtime: Int): Int = {
deploymentTime_Deploy = dtime deploymentTime_Deploy = dtime
DeployTime DeployTime
} }
def DeconstructionTime : Option[FiniteDuration] = deconTime def DeconstructionTime: Option[FiniteDuration] = deconTime
def DeconstructionTime_=(time : FiniteDuration) : Option[FiniteDuration] = { def DeconstructionTime_=(time: FiniteDuration): Option[FiniteDuration] = {
deconTime_=(Some(time)) deconTime_=(Some(time))
DeconstructionTime DeconstructionTime
} }
def DeconstructionTime_=(time : Option[FiniteDuration]) : Option[FiniteDuration] = { def DeconstructionTime_=(time: Option[FiniteDuration]): Option[FiniteDuration] = {
deconTime = time deconTime = time
DeconstructionTime DeconstructionTime
} }
def UndeployTime : Int = deploymentTime_Undeploy def UndeployTime: Int = deploymentTime_Undeploy
def UndeployTime_=(dtime : Int) : Int = { def UndeployTime_=(dtime: Int): Int = {
deploymentTime_Undeploy = dtime deploymentTime_Undeploy = dtime
UndeployTime UndeployTime
} }
def TrunkSize : InventoryTile = trunkSize def TrunkSize: InventoryTile = trunkSize
def TrunkSize_=(tile : InventoryTile) : InventoryTile = { def TrunkSize_=(tile: InventoryTile): InventoryTile = {
trunkSize = tile trunkSize = tile
TrunkSize TrunkSize
} }
def TrunkOffset : Int = trunkOffset def TrunkOffset: Int = trunkOffset
def TrunkOffset_=(offset : Int) : Int = { def TrunkOffset_=(offset: Int): Int = {
trunkOffset = offset trunkOffset = offset
TrunkOffset TrunkOffset
} }
def TrunkLocation : Vector3 = trunkLocation def TrunkLocation: Vector3 = trunkLocation
def TrunkLocation_=(location : Vector3) : Vector3 = { def TrunkLocation_=(location: Vector3): Vector3 = {
trunkLocation = location trunkLocation = location
TrunkLocation TrunkLocation
} }
def AutoPilotSpeeds : (Int, Int) = serverVehicleOverrideSpeeds def AutoPilotSpeeds: (Int, Int) = serverVehicleOverrideSpeeds
def AutoPilotSpeeds_=(speeds : (Int, Int)) : (Int, Int) = { def AutoPilotSpeeds_=(speeds: (Int, Int)): (Int, Int) = {
serverVehicleOverrideSpeeds = speeds serverVehicleOverrideSpeeds = speeds
AutoPilotSpeeds AutoPilotSpeeds
} }
def AutoPilotSpeed1 : Int = serverVehicleOverrideSpeeds._1 def AutoPilotSpeed1: Int = serverVehicleOverrideSpeeds._1
def AutoPilotSpeed2 : Int = serverVehicleOverrideSpeeds._2 def AutoPilotSpeed2: Int = serverVehicleOverrideSpeeds._2
def MaxNtuCapacitor : Int = maxNtuCapacitor def MaxNtuCapacitor: Int = maxNtuCapacitor
def MaxNtuCapacitor_=(max: Int) : Int = { def MaxNtuCapacitor_=(max: Int): Int = {
maxNtuCapacitor = max maxNtuCapacitor = max
MaxNtuCapacitor MaxNtuCapacitor
} }
def MaxCapacitor : Int = maxCapacitor def MaxCapacitor: Int = maxCapacitor
def MaxCapacitor_=(max: Int) : Int = { def MaxCapacitor_=(max: Int): Int = {
maxCapacitor = max maxCapacitor = max
MaxCapacitor MaxCapacitor
} }
private var jackDuration = Array(0, 0, 0, 0) private var jackDuration = Array(0, 0, 0, 0)
def JackingDuration: Array[Int] = jackDuration def JackingDuration: Array[Int] = jackDuration
def JackingDuration_=(arr: Array[Int]) : Array[Int] = { def JackingDuration_=(arr: Array[Int]): Array[Int] = {
jackDuration = arr jackDuration = arr
arr arr
} }
def DestroyedModel : Option[DestroyedVehicle.Value] = destroyedModel def DestroyedModel: Option[DestroyedVehicle.Value] = destroyedModel
def DestroyedModel_=(model : Option[DestroyedVehicle.Value]) : Option[DestroyedVehicle.Value] = { def DestroyedModel_=(model: Option[DestroyedVehicle.Value]): Option[DestroyedVehicle.Value] = {
destroyedModel = model destroyedModel = model
DestroyedModel DestroyedModel
} }
@ -191,7 +193,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
object VehicleDefinition { object VehicleDefinition {
private val converter = new VehicleConverter private val converter = new VehicleConverter
def apply(objectId: Int) : VehicleDefinition = { def apply(objectId: Int): VehicleDefinition = {
new VehicleDefinition(objectId) new VehicleDefinition(objectId)
} }
} }

View file

@ -8,7 +8,7 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Success, Try} import scala.util.{Success, Try}
class ACEConverter extends ObjectCreateConverter[ConstructionItem]() { class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
override def ConstructorData(obj : ConstructionItem) : Try[HandheldData] = { override def ConstructorData(obj: ConstructionItem): Try[HandheldData] = {
Success( Success(
HandheldData( HandheldData(
CommonFieldData( CommonFieldData(
@ -27,7 +27,7 @@ class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
) )
} }
override def DetailedConstructorData(obj : ConstructionItem) : Try[DetailedConstructionToolData] = { override def DetailedConstructorData(obj: ConstructionItem): Try[DetailedConstructionToolData] = {
Success( Success(
DetailedConstructionToolData( DetailedConstructionToolData(
CommonFieldData( CommonFieldData(

View file

@ -8,11 +8,11 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try} import scala.util.{Success, Try}
class AmmoBoxConverter extends ObjectCreateConverter[AmmoBox] { class AmmoBoxConverter extends ObjectCreateConverter[AmmoBox] {
override def ConstructorData(obj : AmmoBox) : Try[CommonFieldData] = { override def ConstructorData(obj: AmmoBox): Try[CommonFieldData] = {
Success(CommonFieldData()(false)) Success(CommonFieldData()(false))
} }
override def DetailedConstructorData(obj : AmmoBox) : Try[DetailedAmmoBoxData] = { override def DetailedConstructorData(obj: AmmoBox): Try[DetailedAmmoBoxData] = {
Success( Success(
DetailedAmmoBoxData( DetailedAmmoBoxData(
CommonFieldData( CommonFieldData(

View file

@ -10,10 +10,10 @@ import scala.annotation.tailrec
import scala.util.{Success, Try} import scala.util.{Success, Try}
class AvatarConverter extends ObjectCreateConverter[Player]() { class AvatarConverter extends ObjectCreateConverter[Player]() {
override def ConstructorData(obj : Player) : Try[PlayerData] = { override def ConstructorData(obj: Player): Try[PlayerData] = {
import AvatarConverter._ import AvatarConverter._
Success( Success(
if(obj.VehicleSeated.isEmpty) { if (obj.VehicleSeated.isEmpty) {
PlayerData( PlayerData(
PlacementData(obj.Position, obj.Orientation, obj.Velocity), PlacementData(obj.Position, obj.Orientation, obj.Velocity),
MakeAppearanceData(obj), MakeAppearanceData(obj),
@ -21,8 +21,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
MakeInventoryData(obj), MakeInventoryData(obj),
GetDrawnSlot(obj) GetDrawnSlot(obj)
) )
} } else {
else {
PlayerData( PlayerData(
MakeAppearanceData(obj), MakeAppearanceData(obj),
MakeCharacterData(obj), MakeCharacterData(obj),
@ -33,10 +32,10 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
) )
} }
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = { override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
import AvatarConverter._ import AvatarConverter._
Success( Success(
if(obj.VehicleSeated.isEmpty) { if (obj.VehicleSeated.isEmpty) {
DetailedPlayerData.apply( DetailedPlayerData.apply(
PlacementData(obj.Position, obj.Orientation, obj.Velocity), PlacementData(obj.Position, obj.Orientation, obj.Velocity),
MakeAppearanceData(obj), MakeAppearanceData(obj),
@ -44,8 +43,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
MakeDetailedInventoryData(obj), MakeDetailedInventoryData(obj),
GetDrawnSlot(obj) GetDrawnSlot(obj)
) )
} } else {
else {
DetailedPlayerData.apply( DetailedPlayerData.apply(
MakeAppearanceData(obj), MakeAppearanceData(obj),
MakeDetailedCharacterData(obj), MakeDetailedCharacterData(obj),
@ -58,14 +56,15 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
} }
object AvatarConverter { object AvatarConverter {
/** /**
* Compose some data from a `Player` into a representation common to both `CharacterData` and `DetailedCharacterData`. * Compose some data from a `Player` into a representation common to both `CharacterData` and `DetailedCharacterData`.
* @param obj the `Player` game object * @param obj the `Player` game object
* @return the resulting `CharacterAppearanceData` * @return the resulting `CharacterAppearanceData`
*/ */
def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = { def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val alt_model_flag : Boolean = obj.isBackpack val alt_model_flag: Boolean = obj.isBackpack
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA( val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, obj.Voice), BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, obj.Voice),
CommonFieldData( CommonFieldData(
obj.Faction, obj.Faction,
@ -86,7 +85,7 @@ object AvatarConverter {
0, 0,
0 0
) )
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB( val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L, 0L,
outfit_name = "", outfit_name = "",
outfit_logo = 0, outfit_logo = 0,
@ -109,14 +108,13 @@ object AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars()) CharacterAppearanceData(aa, ab, RibbonBars())
} }
def MakeCharacterData(obj : Player) : (Boolean,Boolean)=>CharacterData = { def MakeCharacterData(obj: Player): (Boolean, Boolean) => CharacterData = {
val MaxArmor = obj.MaxArmor val MaxArmor = obj.MaxArmor
CharacterData( CharacterData(
StatConverter.Health(obj.Health, obj.MaxHealth), StatConverter.Health(obj.Health, obj.MaxHealth),
if(MaxArmor == 0) { if (MaxArmor == 0) {
0 0
} } else {
else {
StatConverter.Health(obj.Armor, MaxArmor) StatConverter.Health(obj.Armor, MaxArmor)
}, },
DressBattleRank(obj), DressBattleRank(obj),
@ -127,43 +125,59 @@ object AvatarConverter {
) )
} }
def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = { def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val bep : Long = obj.BEP val bep: Long = obj.BEP
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None } val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
val ba : DetailedCharacterA = DetailedCharacterA( else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep, bep,
obj.CEP, obj.CEP,
0L, 0L, 0L, 0L,
obj.MaxHealth, obj.Health, 0L,
0L,
obj.MaxHealth,
obj.Health,
false, false,
obj.Armor, obj.Armor,
0L, 0L,
obj.MaxStamina, obj.Stamina, obj.MaxStamina,
obj.Stamina,
maxOpt, maxOpt,
0, 0, 0L, 0,
0,
0L,
List(0, 0, 0, 0, 0, 0), List(0, 0, 0, 0, 0, 0),
obj.Certifications.toList.sortBy(_.id) //TODO is sorting necessary? obj.Certifications.toList.sortBy(_.id) //TODO is sorting necessary?
) )
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB( val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None, None,
MakeImplantEntries(obj), MakeImplantEntries(obj),
Nil, Nil, Nil,
Nil,
obj.FirstTimeEvents, obj.FirstTimeEvents,
tutorials = List.empty[String], //TODO tutorial list tutorials = List.empty[String], //TODO tutorial list
0L, 0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)), Some(DCDExtra2(0, 0)),
Nil, Nil, false, Nil,
Nil,
false,
MakeCosmetics(obj) MakeCosmetics(obj)
) )
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length) pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
} }
def MakeInventoryData(obj : Player) : InventoryData = { def MakeInventoryData(obj: Player): InventoryData = {
InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot)) InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot))
} }
def MakeDetailedInventoryData(obj : Player) : InventoryData = { def MakeDetailedInventoryData(obj: Player): InventoryData = {
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)) InventoryData(
(MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)
)
} }
/** /**
@ -172,18 +186,15 @@ object AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return the resulting uniform upgrade level * @return the resulting uniform upgrade level
*/ */
private def DressBattleRank(obj : Player) : UniformStyle.Value = { private def DressBattleRank(obj: Player): UniformStyle.Value = {
val bep : Long = obj.BEP val bep: Long = obj.BEP
if(bep > 2583440) { //BR25+ if (bep > 2583440) { //BR25+
UniformStyle.ThirdUpgrade UniformStyle.ThirdUpgrade
} } else if (bep > 308989) { //BR14+
else if(bep > 308989) { //BR14+
UniformStyle.SecondUpgrade UniformStyle.SecondUpgrade
} } else if (bep > 44999) { //BR7+
else if(bep > 44999) { //BR7+
UniformStyle.FirstUpgrade UniformStyle.FirstUpgrade
} } else { //BR1+
else { //BR1+
UniformStyle.Normal UniformStyle.Normal
} }
} }
@ -194,24 +205,19 @@ object AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return the resulting uniform upgrade level * @return the resulting uniform upgrade level
*/ */
private def DressCommandRank(obj : Player) : Int = { private def DressCommandRank(obj: Player): Int = {
val cep = obj.CEP val cep = obj.CEP
if(cep > 599999) { if (cep > 599999) {
5 5
} } else if (cep > 299999) {
else if(cep > 299999) {
4 4
} } else if (cep > 149999) {
else if(cep > 149999) {
3 3
} } else if (cep > 49999) {
else if(cep > 49999) {
2 2
} } else if (cep > 9999) {
else if(cep > 9999) {
1 1
} } else {
else {
0 0
} }
} }
@ -222,17 +228,19 @@ object AvatarConverter {
* @return the resulting implant `List` * @return the resulting implant `List`
* @see `ImplantEntry` in `DetailedCharacterData` * @see `ImplantEntry` in `DetailedCharacterData`
*/ */
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = { private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
//val numImplants : Int = DetailedCharacterData.numberOfImplantSlots(obj.BEP) //val numImplants : Int = DetailedCharacterData.numberOfImplantSlots(obj.BEP)
//val implants = obj.Implants //val implants = obj.Implants
obj.Implants.map({ case(implant, initialization, _) => obj.Implants
if(initialization == 0) { .map({
case (implant, initialization, _) =>
if (initialization == 0) {
ImplantEntry(implant, None) ImplantEntry(implant, None)
} else {
ImplantEntry(implant, Some(math.max(0, initialization).toInt))
} }
else { })
ImplantEntry(implant, Some(math.max(0,initialization).toInt)) .toList
}
}).toList
} }
/** /**
@ -240,12 +248,12 @@ object AvatarConverter {
* @param implants a `Sequence` of `ImplantSlot` objects * @param implants a `Sequence` of `ImplantSlot` objects
* @return the effect of an active implant * @return the effect of an active implant
*/ */
private def MakeImplantEffectList(implants : Seq[(ImplantType.Value, Long, Boolean)]) : List[ImplantEffects.Value] = { private def MakeImplantEffectList(implants: Seq[(ImplantType.Value, Long, Boolean)]): List[ImplantEffects.Value] = {
implants.collect { implants.collect {
case (ImplantType.AdvancedRegen,_,true) => ImplantEffects.RegenEffects case (ImplantType.AdvancedRegen, _, true) => ImplantEffects.RegenEffects
case (ImplantType.DarklightVision,_,true) => ImplantEffects.DarklightEffects case (ImplantType.DarklightVision, _, true) => ImplantEffects.DarklightEffects
case (ImplantType.PersonalShield,_,true) => ImplantEffects.PersonalShieldEffects case (ImplantType.PersonalShield, _, true) => ImplantEffects.PersonalShieldEffects
case (ImplantType.Surge,_,true) => ImplantEffects.SurgeEffects case (ImplantType.Surge, _, true) => ImplantEffects.SurgeEffects
}.toList }.toList
} }
@ -257,11 +265,10 @@ object AvatarConverter {
* @see `Cosmetics` * @see `Cosmetics`
* @return the `Cosmetics` options * @return the `Cosmetics` options
*/ */
def MakeCosmetics(obj : Player) : Option[Cosmetics] = def MakeCosmetics(obj: Player): Option[Cosmetics] =
if(DetailedCharacterData.isBR24(obj.BEP)) { if (DetailedCharacterData.isBR24(obj.BEP)) {
obj.PersonalStyleFeatures.orElse(Some(Cosmetics())) obj.PersonalStyleFeatures.orElse(Some(Cosmetics()))
} } else {
else {
None None
} }
@ -272,11 +279,16 @@ object AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return a list of all items that were in the inventory in decoded packet form * @return a list of all items that were in the inventory in decoded packet form
*/ */
private def MakeInventory(obj : Player) : List[InternalSlot] = { private def MakeInventory(obj: Player): List[InternalSlot] = {
obj.Inventory.Items obj.Inventory.Items
.map(item => { .map(item => {
val equip : Equipment = item.obj val equip: Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get) InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
}) })
} }
@ -289,7 +301,7 @@ object AvatarConverter {
* @param builder the function used to transform to the decoded packet form * @param builder the function used to transform to the decoded packet form
* @return a list of all items that were in the holsters in decoded packet form * @return a list of all items that were in the holsters in decoded packet form
*/ */
private def MakeHolsters(obj : Player, builder : (Int, Equipment) => InternalSlot) : List[InternalSlot] = { private def MakeHolsters(obj: Player, builder: (Int, Equipment) => InternalSlot): List[InternalSlot] = {
recursiveMakeHolsters(obj.Holsters().iterator, builder) recursiveMakeHolsters(obj.Holsters().iterator, builder)
} }
@ -300,7 +312,7 @@ object AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return a list of any item that was in the fifth holster in decoded packet form * @return a list of any item that was in the fifth holster in decoded packet form
*/ */
private def MakeFifthSlot(obj : Player) : List[InternalSlot] = { private def MakeFifthSlot(obj: Player): List[InternalSlot] = {
obj.Slot(5).Equipment match { obj.Slot(5).Equipment match {
case Some(equip) => case Some(equip) =>
BuildDetailedEquipment(5, equip) :: Nil BuildDetailedEquipment(5, equip) :: Nil
@ -315,7 +327,7 @@ object AvatarConverter {
* @param equip the game object * @param equip the game object
* @return the game object in decoded packet form * @return the game object in decoded packet form
*/ */
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = { private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.ConstructorData(equip).get) InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.ConstructorData(equip).get)
} }
@ -325,8 +337,13 @@ object AvatarConverter {
* @param equip the game object * @param equip the game object
* @return the game object in decoded packet form * @return the game object in decoded packet form
*/ */
def BuildDetailedEquipment(index : Int, equip : Equipment) : InternalSlot = { def BuildDetailedEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get) InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
index,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
} }
/** /**
@ -337,22 +354,25 @@ object AvatarConverter {
* @param index which holster is currently being explored * @param index which holster is currently being explored
* @return the `List` of inventory data created from the holsters * @return the `List` of inventory data created from the holsters
*/ */
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], builder : (Int, Equipment) => InternalSlot, list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = { @tailrec private def recursiveMakeHolsters(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
builder: (Int, Equipment) => InternalSlot,
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list list
} } else {
else { val slot: EquipmentSlot = iter.next
val slot : EquipmentSlot = iter.next if (slot.Equipment.isDefined) {
if(slot.Equipment.isDefined) { val equip: Equipment = slot.Equipment.get
val equip : Equipment = slot.Equipment.get
recursiveMakeHolsters( recursiveMakeHolsters(
iter, iter,
builder, builder,
list :+ builder(index, equip), list :+ builder(index, equip),
index + 1 index + 1
) )
} } else {
else {
recursiveMakeHolsters(iter, builder, list, index + 1) recursiveMakeHolsters(iter, builder, list, index + 1)
} }
} }
@ -363,7 +383,7 @@ object AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return the holster's Enumeration value * @return the holster's Enumeration value
*/ */
def GetDrawnSlot(obj : Player) : DrawnSlot.Value = { def GetDrawnSlot(obj: Player): DrawnSlot.Value = {
obj.DrawnSlot match { obj.DrawnSlot match {
case Player.HandsDownSlot | Player.FreeHandSlot => DrawnSlot.None case Player.HandsDownSlot | Player.FreeHandSlot => DrawnSlot.None
case n => DrawnSlot(n) case n => DrawnSlot(n)

View file

@ -8,13 +8,15 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try} import scala.util.{Success, Try}
class BoomerTriggerConverter extends ObjectCreateConverter[SimpleItem]() { class BoomerTriggerConverter extends ObjectCreateConverter[SimpleItem]() {
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = { override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
Success(HandheldData(CommonFieldData())) Success(HandheldData(CommonFieldData()))
} }
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedConstructionToolData] = { override def DetailedConstructorData(obj: SimpleItem): Try[DetailedConstructionToolData] = {
Success(DetailedConstructionToolData( Success(
DetailedConstructionToolData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)) CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
)) )
)
} }
} }

View file

@ -2,7 +2,7 @@
package net.psforever.objects.definition.converter package net.psforever.objects.definition.converter
import net.psforever.objects.{Player, Tool} import net.psforever.objects.{Player, Tool}
import net.psforever.objects.equipment.{Equipment, EquipmentSlot} import net.psforever.objects.equipment.EquipmentSlot
import net.psforever.packet.game.objectcreate._ import net.psforever.packet.game.objectcreate._
import net.psforever.types.{PlanetSideGUID, _} import net.psforever.types.{PlanetSideGUID, _}
@ -15,9 +15,10 @@ import scala.util.{Failure, Success, Try}
* Details that would not be apparent on that screen such as implants or certifications are ignored. * Details that would not be apparent on that screen such as implants or certifications are ignored.
*/ */
class CharacterSelectConverter extends AvatarConverter { class CharacterSelectConverter extends AvatarConverter {
override def ConstructorData(obj : Player) : Try[PlayerData] = Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData")) override def ConstructorData(obj: Player): Try[PlayerData] =
Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = { override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
Success( Success(
DetailedPlayerData.apply( DetailedPlayerData.apply(
PlacementData(0, 0, 0), PlacementData(0, 0, 0),
@ -35,8 +36,8 @@ class CharacterSelectConverter extends AvatarConverter {
* @see `AvatarConverter.MakeAppearanceData` * @see `AvatarConverter.MakeAppearanceData`
* @return the resulting `CharacterAppearanceData` * @return the resulting `CharacterAppearanceData`
*/ */
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = { private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA( val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, CharacterVoice.Mute), BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, CharacterVoice.Mute),
CommonFieldData( CommonFieldData(
obj.Faction, obj.Faction,
@ -57,7 +58,7 @@ class CharacterSelectConverter extends AvatarConverter {
0, 0,
0 0
) )
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB( val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L, 0L,
outfit_name = "", outfit_name = "",
outfit_logo = 0, outfit_logo = 0,
@ -80,35 +81,49 @@ class CharacterSelectConverter extends AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars()) CharacterAppearanceData(aa, ab, RibbonBars())
} }
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = { private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val bep : Long = obj.BEP val bep: Long = obj.BEP
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None } val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
val ba : DetailedCharacterA = DetailedCharacterA( else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep, bep,
obj.CEP, obj.CEP,
0L, 0L, 0L, 0L,
1, 1, 0L,
0L,
1,
1,
false, false,
0, 0,
0L, 0L,
1, 1, 1,
1,
maxOpt, maxOpt,
0, 0, 0L, 0,
0,
0L,
List(0, 0, 0, 0, 0, 0), List(0, 0, 0, 0, 0, 0),
certs = List.empty[CertificationType.Value] certs = List.empty[CertificationType.Value]
) )
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB( val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None, None,
MakeImplantEntries(obj), //necessary for correct stream length MakeImplantEntries(obj), //necessary for correct stream length
Nil, Nil, Nil,
Nil,
firstTimeEvents = List.empty[String], firstTimeEvents = List.empty[String],
tutorials = List.empty[String], tutorials = List.empty[String],
0L, 0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)), Some(DCDExtra2(0, 0)),
Nil, Nil, false, Nil,
Nil,
false,
AvatarConverter.MakeCosmetics(obj) AvatarConverter.MakeCosmetics(obj)
) )
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length) pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
} }
/** /**
@ -117,7 +132,7 @@ class CharacterSelectConverter extends AvatarConverter {
* @return the resulting implant `List` * @return the resulting implant `List`
* @see `ImplantEntry` in `DetailedCharacterData` * @see `ImplantEntry` in `DetailedCharacterData`
*/ */
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = { private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
List.fill[ImplantEntry](DetailedCharacterData.numberOfImplantSlots(obj.BEP))(ImplantEntry(ImplantType.None, None)) List.fill[ImplantEntry](DetailedCharacterData.numberOfImplantSlots(obj.BEP))(ImplantEntry(ImplantType.None, None))
} }
@ -129,14 +144,17 @@ class CharacterSelectConverter extends AvatarConverter {
* @see `AvatarConverter.recursiveMakeHolsters` * @see `AvatarConverter.recursiveMakeHolsters`
* @return the `List` of inventory data created from the holsters * @return the `List` of inventory data created from the holsters
*/ */
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = { @tailrec private def recursiveMakeHolsters(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list list
} } else {
else { val slot: EquipmentSlot = iter.next
val slot : EquipmentSlot = iter.next
slot.Equipment match { slot.Equipment match {
case Some(equip : Tool) => case Some(equip: Tool) =>
val jammed = equip.Jammed val jammed = equip.Jammed
equip.Jammed = false equip.Jammed = false
val slot = AvatarConverter.BuildDetailedEquipment(index, equip) val slot = AvatarConverter.BuildDetailedEquipment(index, equip)

View file

@ -3,12 +3,12 @@ package net.psforever.objects.definition.converter
import net.psforever.objects.SimpleItem import net.psforever.objects.SimpleItem
import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedCommandDetonaterData, HandheldData} import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedCommandDetonaterData, HandheldData}
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID} import net.psforever.types.PlanetSideGUID
import scala.util.{Success, Try} import scala.util.{Success, Try}
class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() { class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = { override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
Success( Success(
HandheldData( HandheldData(
CommonFieldData( CommonFieldData(
@ -26,7 +26,7 @@ class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
) )
} }
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedCommandDetonaterData] = { override def DetailedConstructorData(obj: SimpleItem): Try[DetailedCommandDetonaterData] = {
Success( Success(
DetailedCommandDetonaterData( DetailedCommandDetonaterData(
CommonFieldData( CommonFieldData(

View file

@ -10,13 +10,13 @@ import scala.annotation.tailrec
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class CorpseConverter extends AvatarConverter { class CorpseConverter extends AvatarConverter {
override def ConstructorData(obj : Player) : Try[PlayerData] = override def ConstructorData(obj: Player): Try[PlayerData] =
Failure(new Exception("CorpseConverter should not be used to generate CharacterData")) Failure(new Exception("CorpseConverter should not be used to generate CharacterData"))
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = { override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
Success( Success(
DetailedPlayerData.apply( DetailedPlayerData.apply(
PlacementData(obj.Position, Vector3(0,0, obj.Orientation.z)), PlacementData(obj.Position, Vector3(0, 0, obj.Orientation.z)),
MakeAppearanceData(obj), MakeAppearanceData(obj),
MakeDetailedCharacterData(obj), MakeDetailedCharacterData(obj),
InventoryData((MakeHolsters(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)), InventoryData((MakeHolsters(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)),
@ -30,8 +30,8 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return the resulting `CharacterAppearanceData` * @return the resulting `CharacterAppearanceData`
*/ */
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = { private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA( val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, CharacterGender.Male, 0, CharacterVoice.Mute), BasicCharacterData(obj.Name, obj.Faction, CharacterGender.Male, 0, CharacterVoice.Mute),
CommonFieldData( CommonFieldData(
obj.Faction, obj.Faction,
@ -52,7 +52,7 @@ class CorpseConverter extends AvatarConverter {
0, 0,
0 0
) )
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB( val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L, 0L,
outfit_name = "", outfit_name = "",
outfit_logo = 0, outfit_logo = 0,
@ -75,34 +75,48 @@ class CorpseConverter extends AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars()) CharacterAppearanceData(aa, ab, RibbonBars())
} }
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = { private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None } val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
val ba : DetailedCharacterA = DetailedCharacterA( else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep = 0L, bep = 0L,
cep = 0L, cep = 0L,
0L, 0L, 0L, 0L,
0, 0, 0L,
0L,
0,
0,
false, false,
0, 0,
0L, 0L,
0, 0, 0,
0,
maxOpt, maxOpt,
0, 0, 0L, 0,
0,
0L,
List(0, 0, 0, 0, 0, 0), List(0, 0, 0, 0, 0, 0),
certs = List.empty[CertificationType.Value] certs = List.empty[CertificationType.Value]
) )
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB( val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None, None,
implants = List.empty[ImplantEntry], implants = List.empty[ImplantEntry],
Nil, Nil, Nil,
Nil,
firstTimeEvents = List.empty[String], firstTimeEvents = List.empty[String],
tutorials = List.empty[String], tutorials = List.empty[String],
0L, 0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)), Some(DCDExtra2(0, 0)),
Nil, Nil, false, Nil,
Nil,
false,
cosmetics = None cosmetics = None
) )
(pad_length : Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length) (pad_length: Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length)
} }
/** /**
@ -112,10 +126,10 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return a list of all items that were in the inventory in decoded packet form * @return a list of all items that were in the inventory in decoded packet form
*/ */
private def MakeInventory(obj : Player) : List[InternalSlot] = { private def MakeInventory(obj: Player): List[InternalSlot] = {
obj.Inventory.Items obj.Inventory.Items
.map(item => { .map(item => {
val equip : Equipment = item.obj val equip: Equipment = item.obj
BuildEquipment(item.start, equip) BuildEquipment(item.start, equip)
}) })
} }
@ -128,7 +142,7 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object * @param obj the `Player` game object
* @return a list of all items that were in the holsters in decoded packet form * @return a list of all items that were in the holsters in decoded packet form
*/ */
private def MakeHolsters(obj : Player) : List[InternalSlot] = { private def MakeHolsters(obj: Player): List[InternalSlot] = {
recursiveMakeHolsters(obj.Holsters().iterator) recursiveMakeHolsters(obj.Holsters().iterator)
} }
@ -139,21 +153,23 @@ class CorpseConverter extends AvatarConverter {
* @param index which holster is currently being explored * @param index which holster is currently being explored
* @return the `List` of inventory data created from the holsters * @return the `List` of inventory data created from the holsters
*/ */
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = { @tailrec private def recursiveMakeHolsters(
if(!iter.hasNext) { iter: Iterator[EquipmentSlot],
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list list
} } else {
else { val slot: EquipmentSlot = iter.next
val slot : EquipmentSlot = iter.next if (slot.Equipment.isDefined) {
if(slot.Equipment.isDefined) { val equip: Equipment = slot.Equipment.get
val equip : Equipment = slot.Equipment.get
recursiveMakeHolsters( recursiveMakeHolsters(
iter, iter,
list :+ BuildEquipment(index, equip), list :+ BuildEquipment(index, equip),
index + 1 index + 1
) )
} } else {
else {
recursiveMakeHolsters(iter, list, index + 1) recursiveMakeHolsters(iter, list, index + 1)
} }
} }
@ -165,8 +181,13 @@ class CorpseConverter extends AvatarConverter {
* @param equip the game object * @param equip the game object
* @return the game object in decoded packet form * @return the game object in decoded packet form
*/ */
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = { private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get) InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
index,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
} }
} }

View file

@ -7,14 +7,17 @@ import net.psforever.packet.game.objectcreate.{DestroyedVehicleData, PlacementDa
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class DestroyedVehicleConverter extends ObjectCreateConverter[Vehicle]() { class DestroyedVehicleConverter extends ObjectCreateConverter[Vehicle]() {
override def DetailedConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] = override def DetailedConstructorData(obj: Vehicle): Try[DestroyedVehicleData] =
Failure(new Exception("DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)")) Failure(
new Exception(
"DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)"
)
)
override def ConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] = { override def ConstructorData(obj: Vehicle): Try[DestroyedVehicleData] = {
if(obj.Health > 0) { if (obj.Health > 0) {
Failure(new Exception("Vehicle used on DestroyedVehicleConverter has not yet been destroyed (Health == 0)")) Failure(new Exception("Vehicle used on DestroyedVehicleConverter has not yet been destroyed (Health == 0)"))
} } else {
else {
Success(DestroyedVehicleData(PlacementData(obj.Position, obj.Orientation))) Success(DestroyedVehicleData(PlacementData(obj.Position, obj.Orientation)))
} }
} }

View file

@ -8,12 +8,12 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class DroppodConverter extends ObjectCreateConverter[Vehicle]() { class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
override def DetailedConstructorData(obj : Vehicle) : Try[DroppodData] = override def DetailedConstructorData(obj: Vehicle): Try[DroppodData] =
Failure(new Exception("DroppodConverter should not be used to generate detailed DroppodData (nothing should)")) Failure(new Exception("DroppodConverter should not be used to generate detailed DroppodData (nothing should)"))
override def ConstructorData(obj : Vehicle) : Try[DroppodData] = { override def ConstructorData(obj: Vehicle): Try[DroppodData] = {
val health = StatConverter.Health(obj.Health, obj.MaxHealth) val health = StatConverter.Health(obj.Health, obj.MaxHealth)
if(health > 0) { //active if (health > 0) { //active
Success( Success(
DroppodData( DroppodData(
CommonFieldDataWithPlacement( CommonFieldDataWithPlacement(
@ -38,8 +38,7 @@ class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
unk = false unk = false
) )
) )
} } else { //destroyed
else { //destroyed
Success( Success(
DroppodData( DroppodData(
CommonFieldDataWithPlacement( CommonFieldDataWithPlacement(

View file

@ -10,9 +10,9 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() { class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
override def ConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] = { override def ConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] = {
val health = StatConverter.Health(obj.Health, obj.MaxHealth) val health = StatConverter.Health(obj.Health, obj.MaxHealth)
if(health > 3) { if (health > 3) {
Success( Success(
OneMannedFieldTurretData( OneMannedFieldTurretData(
CommonFieldDataWithPlacement( CommonFieldDataWithPlacement(
@ -36,8 +36,7 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
Some(InventoryData(FieldTurretConverter.MakeMountings(obj))) Some(InventoryData(FieldTurretConverter.MakeMountings(obj)))
) )
) )
} } else {
else {
Success( Success(
OneMannedFieldTurretData( OneMannedFieldTurretData(
CommonFieldDataWithPlacement( CommonFieldDataWithPlacement(
@ -60,17 +59,19 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
} }
} }
override def DetailedConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] = override def DetailedConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] =
Failure(new Exception("converter should not be used to generate detailed OneMannedFieldTurretData")) Failure(new Exception("converter should not be used to generate detailed OneMannedFieldTurretData"))
} }
object FieldTurretConverter { object FieldTurretConverter {
private def MakeMountings(obj : WeaponTurret) : List[InventoryItemData.InventoryItem] = { private def MakeMountings(obj: WeaponTurret): List[InventoryItemData.InventoryItem] = {
obj.Weapons.map({ obj.Weapons
case(index, slot) => .map({
val equip : Equipment = slot.Equipment.get case (index, slot) =>
val equip: Equipment = slot.Equipment.get
val equipDef = equip.Definition val equipDef = equip.Definition
InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get) InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get)
}).toList })
.toList
} }
} }

View file

@ -9,7 +9,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSideGameObject with TelepadLike]() { class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSideGameObject with TelepadLike]() {
override def ConstructorData(obj : PlanetSideGameObject with TelepadLike) : Try[TelepadDeployableData] = { override def ConstructorData(obj: PlanetSideGameObject with TelepadLike): Try[TelepadDeployableData] = {
obj.Router match { obj.Router match {
case Some(PlanetSideGUID(0)) => case Some(PlanetSideGUID(0)) =>
Failure(new IllegalStateException("InternalTelepadDeployableConverter: knowledge of parent Router is null")) Failure(new IllegalStateException("InternalTelepadDeployableConverter: knowledge of parent Router is null"))
@ -34,7 +34,9 @@ class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSid
) )
case None => case None =>
Failure(new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router")) Failure(
new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router")
)
} }
} }
} }

View file

@ -7,11 +7,11 @@ import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedAmmoBoxD
import scala.util.{Success, Try} import scala.util.{Success, Try}
class KitConverter extends ObjectCreateConverter[Kit]() { class KitConverter extends ObjectCreateConverter[Kit]() {
override def ConstructorData(obj : Kit) : Try[CommonFieldData] = { override def ConstructorData(obj: Kit): Try[CommonFieldData] = {
Success(CommonFieldData()(false)) Success(CommonFieldData()(false))
} }
override def DetailedConstructorData(obj : Kit) : Try[DetailedAmmoBoxData] = { override def DetailedConstructorData(obj: Kit): Try[DetailedAmmoBoxData] = {
Success(DetailedAmmoBoxData(0, 1)) Success(DetailedAmmoBoxData(0, 1))
} }
} }

View file

@ -10,7 +10,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try} import scala.util.{Success, Try}
class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]() { class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]() {
override def ConstructorData(obj : LockerEquipment) : Try[LockerContainerData] = { override def ConstructorData(obj: LockerEquipment): Try[LockerContainerData] = {
MakeInventory(obj.Inventory) match { MakeInventory(obj.Inventory) match {
case Nil => case Nil =>
Success(LockerContainerData(None)) Success(LockerContainerData(None))
@ -19,18 +19,21 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
} }
} }
override def DetailedConstructorData(obj : LockerEquipment) : Try[DetailedLockerContainerData] = { override def DetailedConstructorData(obj: LockerEquipment): Try[DetailedLockerContainerData] = {
if(obj.Inventory.Size > 0) { if (obj.Inventory.Size > 0) {
Success(DetailedLockerContainerData( Success(
DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)), CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
Some(InventoryData(MakeDetailedInventory(obj.Inventory))) Some(InventoryData(MakeDetailedInventory(obj.Inventory)))
)) )
} )
else { } else {
Success(DetailedLockerContainerData( Success(
DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)), CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
None None
)) )
)
} }
} }
@ -40,11 +43,16 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
* @param inv the inventory container * @param inv the inventory container
* @return a list of all items that were in the inventory in decoded packet form * @return a list of all items that were in the inventory in decoded packet form
*/ */
private def MakeInventory(inv : GridInventory) : List[InternalSlot] = { private def MakeInventory(inv: GridInventory): List[InternalSlot] = {
inv.Items inv.Items
.map(item => { .map(item => {
val equip : Equipment = item.obj val equip: Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.ConstructorData(equip).get) InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.ConstructorData(equip).get
)
}) })
} }
@ -54,11 +62,16 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
* @param inv the inventory container * @param inv the inventory container
* @return a list of all items that were in the inventory in decoded packet form * @return a list of all items that were in the inventory in decoded packet form
*/ */
private def MakeDetailedInventory(inv : GridInventory) : List[InternalSlot] = { private def MakeDetailedInventory(inv: GridInventory): List[InternalSlot] = {
inv.Items inv.Items
.map(item => { .map(item => {
val equip : Equipment = item.obj val equip: Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get) InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
}) })
} }
} }

View file

@ -17,17 +17,22 @@ sealed trait PacketConverter
* @tparam A the type of game object * @tparam A the type of game object
*/ */
abstract class ObjectCreateConverter[A <: PlanetSideGameObject] extends PacketConverter { abstract class ObjectCreateConverter[A <: PlanetSideGameObject] extends PacketConverter {
/** /**
* Take a game object and transform it into its equivalent data for an `0x17` packet. * Take a game object and transform it into its equivalent data for an `0x17` packet.
* @param obj the game object * @param obj the game object
* @return the specific `ConstructorData` that is equivalent to this object * @return the specific `ConstructorData` that is equivalent to this object
*/ */
def ConstructorData(obj : A) : Try[ConstructorData] = { Failure(new NoSuchMethodException(s"method not defined for object $obj")) } def ConstructorData(obj: A): Try[ConstructorData] = {
Failure(new NoSuchMethodException(s"method not defined for object $obj"))
}
/** /**
* Take a game object and transform it into its equivalent data for an `0x18` packet. * Take a game object and transform it into its equivalent data for an `0x18` packet.
* @param obj the game object * @param obj the game object
* @return the specific `ConstructorData` that is equivalent to this object * @return the specific `ConstructorData` that is equivalent to this object
*/ */
def DetailedConstructorData(obj : A) : Try[ConstructorData] = { Failure(new NoSuchMethodException(s"method not defined for object $obj")) } def DetailedConstructorData(obj: A): Try[ConstructorData] = {
Failure(new NoSuchMethodException(s"method not defined for object $obj"))
}
} }

View file

@ -2,13 +2,19 @@
package net.psforever.objects.definition.converter package net.psforever.objects.definition.converter
import net.psforever.objects.ballistics.Projectile import net.psforever.objects.ballistics.Projectile
import net.psforever.packet.game.objectcreate.{CommonFieldData, CommonFieldDataWithPlacement, FlightPhysics, PlacementData, RemoteProjectileData} import net.psforever.packet.game.objectcreate.{
CommonFieldData,
CommonFieldDataWithPlacement,
FlightPhysics,
PlacementData,
RemoteProjectileData
}
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
class ProjectileConverter extends ObjectCreateConverter[Projectile]() { class ProjectileConverter extends ObjectCreateConverter[Projectile]() {
override def ConstructorData(obj : Projectile) : Try[RemoteProjectileData] = { override def ConstructorData(obj: Projectile): Try[RemoteProjectileData] = {
Success( Success(
RemoteProjectileData( RemoteProjectileData(
CommonFieldDataWithPlacement( CommonFieldDataWithPlacement(
@ -38,6 +44,8 @@ class ProjectileConverter extends ObjectCreateConverter[Projectile]() {
) )
} }
override def DetailedConstructorData(obj : Projectile) : Try[RemoteProjectileData] = override def DetailedConstructorData(obj: Projectile): Try[RemoteProjectileData] =
Failure(new Exception("ProjectileConverter should not be used to generate detailed projectile data (nothing should)")) Failure(
new Exception("ProjectileConverter should not be used to generate detailed projectile data (nothing should)")
)
} }

View file

@ -8,7 +8,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try} import scala.util.{Success, Try}
class REKConverter extends ObjectCreateConverter[SimpleItem]() { class REKConverter extends ObjectCreateConverter[SimpleItem]() {
override def ConstructorData(obj : SimpleItem) : Try[REKData] = { override def ConstructorData(obj: SimpleItem): Try[REKData] = {
Success( Success(
REKData( REKData(
CommonFieldData( CommonFieldData(
@ -20,12 +20,13 @@ class REKConverter extends ObjectCreateConverter[SimpleItem]() {
false, false,
Some(false), Some(false),
None, None,
PlanetSideGUID(0)) PlanetSideGUID(0)
)
) )
) )
} }
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedREKData] = { override def DetailedConstructorData(obj: SimpleItem): Try[DetailedREKData] = {
Success( Success(
DetailedREKData( DetailedREKData(
CommonFieldData( CommonFieldData(

View file

@ -6,7 +6,7 @@ import net.psforever.objects.vehicles.Seat
import net.psforever.packet.game.objectcreate.{InventoryItemData, ObjectClass, PlayerData, VehicleData} import net.psforever.packet.game.objectcreate.{InventoryItemData, ObjectClass, PlayerData, VehicleData}
object SeatConverter { object SeatConverter {
def MakeSeat(player : Player, offset : Long) : PlayerData = { def MakeSeat(player: Player, offset: Long): PlayerData = {
VehicleData.PlayerData( VehicleData.PlayerData(
AvatarConverter.MakeAppearanceData(player), AvatarConverter.MakeAppearanceData(player),
AvatarConverter.MakeCharacterData(player), AvatarConverter.MakeCharacterData(player),
@ -17,15 +17,17 @@ object SeatConverter {
} }
//TODO do not use for now; causes seat access permission issues with many passengers; may not mesh with workflows; GUID requirements //TODO do not use for now; causes seat access permission issues with many passengers; may not mesh with workflows; GUID requirements
def MakeSeats(seats : Map[Int, Seat], initialOffset : Long) : List[InventoryItemData.InventoryItem] = { def MakeSeats(seats: Map[Int, Seat], initialOffset: Long): List[InventoryItemData.InventoryItem] = {
var offset = initialOffset var offset = initialOffset
seats seats
.filter({ case (_, seat) => seat.isOccupied }) .filter({ case (_, seat) => seat.isOccupied })
.map({case (index, seat) => .map({
case (index, seat) =>
val player = seat.Occupant.get val player = seat.Occupant.get
val entry = InventoryItemData(ObjectClass.avatar, player.GUID, index, SeatConverter.MakeSeat(player, offset)) val entry = InventoryItemData(ObjectClass.avatar, player.GUID, index, SeatConverter.MakeSeat(player, offset))
offset += entry.bitsize offset += entry.bitsize
entry entry
}).toList })
.toList
} }
} }

Some files were not shown because too many files have changed in this diff Show more