core/logic/smn_float.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Apr 23 21:40:50 2014 -0400 (2014-04-23)
changeset 4332 75c299312bec
parent 4331 da66b9161507
permissions -rw-r--r--
Update CS:GO gamedata.
     1 /**
     2  * vim: set ts=4 sw=4 tw=99 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include <math.h>
    33 #include <string.h>
    34 #include <stdlib.h>
    35 #include "common_logic.h"
    36 #include "MersenneTwister.h"
    37 #include <IPluginSys.h>
    38 #include <am-utility.h>
    39 
    40 /****************************************
    41 *                                       *
    42 * FLOATING POINT NATIVE IMPLEMENTATIONS *
    43 *                                       *
    44 ****************************************/
    45 
    46 
    47 static cell_t sm_float(IPluginContext *pCtx, const cell_t *params)
    48 {
    49 	float val = static_cast<float>(params[1]);
    50 
    51 	return sp_ftoc(val);
    52 }
    53 
    54 static cell_t sm_FloatAbs(IPluginContext *pCtx, const cell_t *params)
    55 {
    56 	float val = sp_ctof(params[1]);
    57 	val = (val >= 0.0f) ? val : -val;
    58 
    59 	return sp_ftoc(val);
    60 }
    61 
    62 static cell_t sm_FloatAdd(IPluginContext *pCtx, const cell_t *params)
    63 {
    64 	float val = sp_ctof(params[1]) + sp_ctof(params[2]);
    65 
    66 	return sp_ftoc(val);
    67 }
    68 
    69 static cell_t sm_FloatSub(IPluginContext *pCtx, const cell_t *params)
    70 {
    71 	float val = sp_ctof(params[1]) - sp_ctof(params[2]);
    72 
    73 	return sp_ftoc(val);
    74 }
    75 
    76 static cell_t sm_FloatMul(IPluginContext *pCtx, const cell_t *params)
    77 {
    78 	float val = sp_ctof(params[1]) * sp_ctof(params[2]);
    79 
    80 	return sp_ftoc(val);
    81 }
    82 
    83 static cell_t sm_FloatDiv(IPluginContext *pCtx, const cell_t *params)
    84 {
    85 	float val = sp_ctof(params[1]) / sp_ctof(params[2]);
    86 
    87 	return sp_ftoc(val);
    88 }
    89 
    90 static cell_t sm_FloatGt(IPluginContext *pCtx, const cell_t *params)
    91 {
    92 	return !!(sp_ctof(params[1]) > sp_ctof(params[2]));
    93 }
    94 
    95 static cell_t sm_FloatGe(IPluginContext *pCtx, const cell_t *params)
    96 {
    97 	return !!(sp_ctof(params[1]) >= sp_ctof(params[2]));
    98 }
    99 
   100 static cell_t sm_FloatLt(IPluginContext *pCtx, const cell_t *params)
   101 {
   102 	return !!(sp_ctof(params[1]) < sp_ctof(params[2]));
   103 }
   104 
   105 static cell_t sm_FloatLe(IPluginContext *pCtx, const cell_t *params)
   106 {
   107 	return !!(sp_ctof(params[1]) <= sp_ctof(params[2]));
   108 }
   109 
   110 static cell_t sm_FloatEq(IPluginContext *pCtx, const cell_t *params)
   111 {
   112 	return !!(sp_ctof(params[1]) == sp_ctof(params[2]));
   113 }
   114 
   115 static cell_t sm_FloatNe(IPluginContext *pCtx, const cell_t *params)
   116 {
   117 	return !!(sp_ctof(params[1]) != sp_ctof(params[2]));
   118 }
   119 
   120 static cell_t sm_FloatNot(IPluginContext *pCtx, const cell_t *params)
   121 {
   122 	float val = sp_ctof(params[1]);
   123 	if (ke::IsNaN(val))
   124 		return 1;
   125 	return val ? 0 : 1;
   126 }
   127 
   128 static cell_t sm_FloatCompare(IPluginContext *pCtx, const cell_t *params)
   129 {
   130 	float val1 = sp_ctof(params[1]);
   131 	float val2 = sp_ctof(params[2]);
   132 
   133 	if (val1 > val2)
   134 	{
   135 		return 1;
   136 	} else if (val1 < val2) {
   137 		return -1;
   138 	}
   139 
   140 	return 0;
   141 }
   142 
   143 static cell_t sm_Logarithm(IPluginContext *pCtx, const cell_t *params)
   144 {
   145 	float val = sp_ctof(params[1]);
   146 	float base = sp_ctof(params[2]);
   147 
   148 	if ((val <= 0.0f) || (base <= 0.0f))
   149 	{
   150 		return pCtx->ThrowNativeError("Cannot evaluate the logarithm of zero or a negative number (val:%f base:%f)", val, base);
   151 	}
   152 	if (base == 10.0f)
   153 	{
   154 		val = log10(val);
   155 	} else {
   156 		val = log(val) / log(base);
   157 	}
   158 
   159 	return sp_ftoc(val);
   160 }
   161 
   162 static cell_t sm_Exponential(IPluginContext *pCtx, const cell_t *params)
   163 {
   164 	float val = sp_ctof(params[1]);
   165 
   166 	return sp_ftoc(exp(val));
   167 }
   168 
   169 static cell_t sm_Pow(IPluginContext *pCtx, const cell_t *params)
   170 {
   171 	float base = sp_ctof(params[1]);
   172 	float exponent = sp_ctof(params[2]);
   173 
   174 	return sp_ftoc(pow(base, exponent));
   175 }
   176 
   177 static cell_t sm_SquareRoot(IPluginContext *pCtx, const cell_t *params)
   178 {
   179 	float val = sp_ctof(params[1]);
   180 
   181 	if (val < 0.0f)
   182 	{
   183 		return pCtx->ThrowNativeError("Cannot evaluate the square root of a negative number (val:%f)", val);
   184 	}
   185 
   186 	return sp_ftoc(sqrt(val));
   187 }
   188 
   189 static cell_t sm_RoundToNearest(IPluginContext *pCtx, const cell_t *params)
   190 {
   191 	float val = sp_ctof(params[1]);
   192 	val = (float)floor(val + 0.5f);
   193 
   194 	return static_cast<int>(val);
   195 }
   196 
   197 static cell_t sm_RoundToFloor(IPluginContext *pCtx, const cell_t *params)
   198 {
   199 	float val = sp_ctof(params[1]);
   200 	val = floor(val);
   201 
   202 	return static_cast<int>(val);
   203 }
   204 
   205 static cell_t sm_RoundToCeil(IPluginContext *pCtx, const cell_t *params)
   206 {
   207 	float val = sp_ctof(params[1]);
   208 	val = ceil(val);
   209 
   210 	return static_cast<int>(val);
   211 }
   212 
   213 static cell_t sm_RoundToZero(IPluginContext *pCtx, const cell_t *params)
   214 {
   215 	float val = sp_ctof(params[1]);
   216 	if (val >= 0.0f)
   217 	{
   218 		val = floor(val);
   219 	} else {
   220 		val = ceil(val);
   221 	}
   222 
   223 	return static_cast<int>(val);
   224 }
   225 
   226 static cell_t sm_FloatFraction(IPluginContext *pCtx, const cell_t *params)
   227 {
   228 	float val = sp_ctof(params[1]);
   229 	val = val - floor(val);
   230 
   231 	return sp_ftoc(val);
   232 }
   233 
   234 static cell_t sm_Sine(IPluginContext *pCtx, const cell_t *params)
   235 {
   236 	float val = sp_ctof(params[1]);
   237 	val = sin(val);
   238 
   239 	return sp_ftoc(val);
   240 }
   241 
   242 static cell_t sm_Cosine(IPluginContext *pCtx, const cell_t *params)
   243 {
   244 	float val = sp_ctof(params[1]);
   245 	val = cos(val);
   246 
   247 	return sp_ftoc(val);
   248 }
   249 
   250 static cell_t sm_Tangent(IPluginContext *pCtx, const cell_t *params)
   251 {
   252 	float val = sp_ctof(params[1]);
   253 	val = tan(val);
   254 
   255 	return sp_ftoc(val);
   256 }
   257 
   258 static cell_t sm_ArcSine(IPluginContext *pCtx, const cell_t *params)
   259 {
   260 	float val = sp_ctof(params[1]);
   261 	val = asin(val);
   262 
   263 	return sp_ftoc(val);
   264 }
   265 
   266 static cell_t sm_ArcCosine(IPluginContext *pCtx, const cell_t *params)
   267 {
   268 	float val = sp_ctof(params[1]);
   269 	val = acos(val);
   270 
   271 	return sp_ftoc(val);
   272 }
   273 
   274 static cell_t sm_ArcTangent(IPluginContext *pCtx, const cell_t *params)
   275 {
   276 	float val = sp_ctof(params[1]);
   277 	val = atan(val);
   278 
   279 	return sp_ftoc(val);
   280 }
   281 
   282 static cell_t sm_ArcTangent2(IPluginContext *pCtx, const cell_t *params)
   283 {
   284 	float val1 = sp_ctof(params[1]);
   285 	float val2 = sp_ctof(params[2]);
   286 	val1 = atan2(val1, val2);
   287 
   288 	return sp_ftoc(val1);
   289 }
   290 
   291 #if 0
   292 static cell_t sm_FloatRound(IPluginContext *pCtx, const cell_t *params)
   293 {
   294 	float val = sp_ctof(params[1]);
   295 
   296 	switch (params[2])
   297 	{
   298 	case 1:
   299 		{
   300 			val = floor(val);
   301 			break;
   302 		}
   303 	case 2:
   304 		{
   305 			val = ceil(val);
   306 			break;
   307 		}
   308 	case 3:
   309 		{
   310 			if (val >= 0.0f)
   311 			{
   312 				val = floor(val);
   313 			} else {
   314 				val = ceil(val);
   315 			}
   316 			break;
   317 		}
   318 	default:
   319 		{
   320 			val = (float)floor(val + 0.5f);
   321 			break;
   322 		}
   323 	}
   324 
   325 	return static_cast<int>(val);
   326 }
   327 #endif
   328 
   329 class RandomHelpers :
   330 	public SMGlobalClass,
   331 	public IPluginsListener
   332 {
   333 public:
   334 	void OnSourceModAllInitialized()
   335 	{
   336 		pluginsys->AddPluginsListener(this);
   337 	}
   338 
   339 	void OnSourceModShutdown()
   340 	{
   341 		pluginsys->RemovePluginsListener(this);
   342 	}
   343 
   344 	void OnPluginDestroyed(IPlugin *plugin)
   345 	{
   346 		MTRand *mtrand;
   347 		if (plugin->GetProperty("core.logic.mtrand", (void**)&mtrand, true))
   348 		{
   349 			delete mtrand;
   350 		}
   351 	}
   352 	
   353 	MTRand *RandObjForPlugin(IPluginContext *ctx)
   354 	{
   355 		IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
   356 		MTRand *mtrand;	
   357 		if (!plugin->GetProperty("core.logic.mtrand", (void**)&mtrand))
   358 		{
   359 			mtrand = new MTRand();
   360 			plugin->SetProperty("core.logic.mtrand", mtrand);
   361 		}
   362 		return mtrand;
   363 	}
   364 } s_RandHelpers;
   365 
   366 static cell_t GetURandomInt(IPluginContext *ctx, const cell_t *params)
   367 {
   368 	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
   369 	/* Note the sign bit must be stripped off because cell_t is signed,
   370 	 * and this guarantees a range of [0,max_int]
   371 	 */
   372 	return randobj->randInt() & 0x7FFFFFFF;
   373 }
   374 
   375 static cell_t GetURandomFloat(IPluginContext *ctx, const cell_t *params)
   376 {
   377 	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
   378 	return sp_ftoc((float)randobj->rand());
   379 }
   380 
   381 static cell_t SetURandomSeed(IPluginContext *ctx, const cell_t *params)
   382 {
   383 	MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
   384 	cell_t *addr;
   385 	ctx->LocalToPhysAddr(params[1], &addr);
   386 	/* We're 32-bit only. */
   387 	randobj->seed((MTRand::uint32*)addr, params[2]);
   388 	return 1;
   389 }
   390 
   391 REGISTER_NATIVES(floatnatives)
   392 {
   393 	{"float",			sm_float},
   394 	{"FloatMul",		sm_FloatMul},
   395 	{"FloatDiv",		sm_FloatDiv},
   396 	{"FloatAdd",		sm_FloatAdd},
   397 	{"FloatSub",		sm_FloatSub},
   398 	{"FloatFraction",	sm_FloatFraction},
   399 	{"RoundToZero",		sm_RoundToZero},
   400 	{"RoundToCeil",		sm_RoundToCeil},
   401 	{"RoundToFloor",	sm_RoundToFloor},
   402 	{"RoundToNearest",	sm_RoundToNearest},
   403 	{"__FLOAT_GT__",	sm_FloatGt},
   404 	{"__FLOAT_GE__",	sm_FloatGe},
   405 	{"__FLOAT_LT__",	sm_FloatLt},
   406 	{"__FLOAT_LE__",	sm_FloatLe},
   407 	{"__FLOAT_EQ__",	sm_FloatEq},
   408 	{"__FLOAT_NE__",	sm_FloatNe},
   409 	{"__FLOAT_NOT__",	sm_FloatNot},
   410 	{"FloatCompare",	sm_FloatCompare},
   411 	{"SquareRoot",		sm_SquareRoot},
   412 	{"Pow",				sm_Pow},
   413 	{"Exponential",		sm_Exponential},
   414 	{"Logarithm",		sm_Logarithm},
   415 	{"Sine",			sm_Sine},
   416 	{"Cosine",			sm_Cosine},
   417 	{"Tangent",			sm_Tangent},
   418 	{"FloatAbs",		sm_FloatAbs},
   419 	{"ArcTangent",		sm_ArcTangent},
   420 	{"ArcCosine",		sm_ArcCosine},
   421 	{"ArcSine",			sm_ArcSine},
   422 	{"ArcTangent2",		sm_ArcTangent2},
   423 	{"GetURandomInt",	GetURandomInt},
   424 	{"GetURandomFloat",	GetURandomFloat},
   425 	{"SetURandomSeed",	SetURandomSeed},
   426 	{NULL,				NULL}
   427 };
   428